如何根据条件合并长度不等的数据帧

时间:2019-10-17 13:14:46

标签: r

我想知道如何最好地结合以下两个数据框:

df1 <- data.frame(Date = c(1,2,3,4,5,6,7,8,9,10),
                  Altitude=c(100,101,101,102,103,99,98,99,89,70))

> df1
   Date Altitude
1     1      100
2     2      101
3     3      101
4     4      102
5     5      103
6     6       99
7     7       98
8     8       99
9     9       89
10   10       70

df2 <- data.frame(Start = c(1,4,8),Stop = c(3,7,10),Longitude=c(10,12,13))

> df2
  Start Stop Longitude
1     1    3        10
2     4    7        12
3     8   10        13

我基本上需要df2中的第三列,并且经度取决于日期是否在开始和停止之间,结果如下:

   Date Altitude Longitude
1     1      100        10
2     2      101        10
3     3      101        10
4     4      102        12
5     5      103        12
6     6       99        12
7     7       98        12
8     8       99        13
9     9       89        13
10   10       70        13

我一直在尝试各种子集,过滤...,但我只是想不通。任何帮助将不胜感激!

亲切的问候

3 个答案:

答案 0 :(得分:2)

通过dplyr的想法是完成start:stop序列,嵌套和合并,即

library(dplyr)

df2 %>% 
 mutate(Date = mapply(seq, Start, Stop)) %>% 
 tidyr::unnest() %>% 
 select(-c(1, 2)) %>% 
 right_join(df1, by = 'Date')

给出,

   Longitude Date Altitude
1         10    1      100
2         10    2      101
3         10    3      101
4         12    4      102
5         12    5      103
6         12    6       99
7         12    7       98
8         13    8       99
9         13    9       89
10        13   10       70

答案 1 :(得分:1)

这里是使用group_by软件包中的group_modifydplyr函数的整洁的答案(于2019年5月在0.8.1版中引入)。

library(dplyr)    
df1 %>% 
      group_by(Date, Altitude) %>%
      group_modify(~ data.frame(df2 %>% 
                                  filter(.x$Date >= Start, .x$Date <= Stop)) %>% 
                                  select(Longitude), 
                   keep = TRUE)

对于df1中日期和高度的每个唯一组合(即每一行),这会找到与df2中日期范围相对应的经度。

输出是小标题:

# A tibble: 10 x 3
# Groups:   Date, Altitude [10]
    Date Altitude Longitude
   <dbl>    <dbl>     <dbl>
 1     1      100        10
 2     2      101        10
 3     3      101        10
 4     4      102        12
 5     5      103        12
 6     6       99        12
 7     7       98        12
 8     8       99        13
 9     9       89        13
10    10       70        13

答案 2 :(得分:0)

Base R解决方案:

ind <- apply(df2, 1, function(x) which(df1$Date >= x[1] & df1$Date <= x[2]))
df1$Longitude <- unlist(Map(function(x,y) rep(y, length(x)), ind, df2$Longitude))

输出

Date Altitude Longitude
1     1      100        10
2     2      101        10
3     3      101        10
4     4      102        12
5     5      103        12
6     6       99        12
7     7       98        12
8     8       99        13
9     9       89        13
10   10       70        13