Как объединить два кадра данных, если значения столбца не точны?

У меня есть:

  1. Линейно интерполировал данные dFe_env через каждые 1 м и создавал кадр данных (это работает)
  2. Извлечена «Глубина» (на основе скорости погружения) с 30-минутными интервалами (это работает)
  3. Создан столбец «Время», в котором оно увеличивается каждые 30 минут (это работает)

Как я:

  1. Объедините два кадра данных вместе (Bckgd_env2 и bulk_Fe2). В «bulk_Fe2» глубина увеличивается на 1 м, а в «Bckgd_env2» глубина увеличивается на 0,8 м. Могу ли я получить наиболее близкое совпадение «Глубины», извлечь dFe_env на этой глубине и создать новый фрейм данных с глубиной, временем и dFe_env вместе?

    library(dplyr)
    
    Depth    <- c(0, 2, 20, 50, 100, 500, 800, 1000, 1200, 1500)
    dFe_env  <- c(0.2, 0.2, 0.3, 0.4, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1)
    bulk_Fe <- data.frame(Depth, dFe_env)
    
    summary(bulk_Fe)
    is.data.frame(bulk_Fe)
    
    do_interp <- function(dat, Depth = seq(0,1500, by=1)) {
    out <- tibble(Depth = Depth)
    for (var in c("dFe_env")) {
    out[[var]] <- tryCatch(approx(dat$Depth, dat[[var]], Depth)$y, method="ngb", error = function(e) NA_real_)
    }
    out
    }
    
    bulk_Fe2 <- bulk_Fe %>% do(do_interp(.))
    bulk_Fe2
    summary(bulk_Fe2)
    
    D0 <- 0 #Starting depth 
    T0 <- 0 #Starting time of the experiment
    
    r <- 40 #sinking rate per day
    
    r_30min <- r/48 #sinking speed every 30 minutes (There are 48 x 30 minute intervals in 24 hours)
    
    
    days <- round(1501/(r)) #days 1501 is maximum depth
    time <- days * 24 * 60 #minutes
    
    n_steps <- 1501/r_30min
    
    Bckgd_env2 <- data.frame(Depth =seq(from = D0, by= r_30min, length.out = n_steps + 1),
                      Time = seq(from = T0, by= 30, length.out = n_steps + 1))
    head(Bckgd_env2)
    round(Bckgd_env2, digits = 1)
    
    Bckgd_env3 <- merge(Bckgd_env2, bulk_Fe2)  
    Bckgd_env3
    
    plot(Bckgd_env2$dFe_env ~ Bckgd_env2$Depth, ylab="dFe (nmol/L)", xlab="Depth (m)", las=1)
    

person L55    schedule 02.09.2020    source источник
comment
Не уверен, что правильно понимаю константы. Что такое 1501? Что такое 200-секундный блок? 30 минут это 1800 секунд.   -  person Ronak Shah    schedule 02.09.2020
comment
1501 — это максимальная глубина сайта, и я использую ее, чтобы рассчитать, сколько дней должен продолжаться эксперимент. Например, при скорости погружения 40 в сутки эксперимент должен длиться 1501/40 = 37,5 суток. Округлено до 38 дней. Я сделал ошибку - я пытался сделать это блоками по 200 секунд вместо блоков по 30 минут (это то, что мне нужно)   -  person L55    schedule 02.09.2020


Ответы (1)


Вы уже построили механизм интерполяции, который будет полезен для соединения. Но вы не построили его на правильных значениях глубины. Это просто вопрос реорганизации вашего кода.

Начните с построения Bckgd_env2 и только потом вычисляйте bulk_Fe2 и bulk_Fe3:

bulk_Fe2 <- bulk_Fe %>% do(do_interp(., Depth=Bckgd_env2$Depth))
Bckgd_env3 <- merge(Bckgd_env2, bulk_Fe2)
person Pierre Gramme    schedule 02.09.2020
comment
Я также объединяю другие данные, не требующие интерполяции (температура, кислород и т. д.). Это растровые файлы, и данные представлены с интервалом в 1 м, поэтому мне не нужно делать какую-либо интерполяцию. Есть ли способ объединиться, потому что некоторые кадры данных не нуждаются в интерполяции? - person L55; 02.09.2020
comment
Если другие кадры данных не имеют точно такие же значения глубины, как Bckgd_env2, им нужна интерполяция. Возможно, вам нужна постоянная интерполяция (см. ?approx). Вы можете добавить метод в качестве аргумента к вашей функции do_interp(). - person Pierre Gramme; 02.09.2020
comment
Кстати, у вас, вероятно, опечатка в коде: method="ngb" не передается в прибл (и это не сработает) - person Pierre Gramme; 02.09.2020