根据另一个数据帧的值范围从数据框中提取值

时间:2018-03-21 16:42:08

标签: r tidyverse

我试图从数据框(df1)中提取索引值,该数据框表示一系列时间(开始 - 结束)并包含另一个数据帧(df2)中给出的时间。我所需的输出是df3

df1<-data.frame(index=c(1,2,3,4),start=c(5,10,15,20),end=c(10,15,20,25))
df2<-data.frame(time=c(11,17,18,5,5,22))
df3<-data.frame(time=c(11,17,18,5,5,22),index=c(2,3,3,1,1,4))

这有解决方案吗?

3 个答案:

答案 0 :(得分:1)

您可以使用R基本功能执行此操作。 which sapply内部 inds <- apply(df1[,-1], 1, function(x) seq(from=x[1], to=x[2])) index <- sapply(df2$time, function(x){ tmp <- which(x == inds, arr.ind = TRUE); tmp[, "col"] } ) df3 <- data.frame(df2, index) df3 time index 1 11 2 2 17 3 3 18 3 4 5 1 5 5 1 6 8 1 和逻辑比较的组合将为您完成工作。

Use Strict Mode for Redirect URIs

答案 1 :(得分:1)

数据:

df1<-data.frame(index=c(1,2,3,4),start=c(5,10,15,20),end=c(10,15,20,25))
df2<-data.frame(time=c(11,17,18,2,5,5,8,22))

代码:

# get index values and assign it to df2 column
df2$index <- apply( df2, 1, function(x) { with(df1, index[ x[ 'time' ]  >= start & x[ 'time' ] <= end ] ) }) 

输出:

df2
#   time index
# 1   11     2
# 2   17     3
# 3   18     3
# 4    2      
# 5    5     1
# 6    5     1
# 7    8     1
# 8   22     4

答案 2 :(得分:1)

以下是findInterval

的一个选项
ftx <- function(x, y) findInterval(x, y)
df3 <- transform(df2, index = pmax(ftx(time, df1$start), ftx(time, df1$end)))

df3
#   time index
#1   11     2
#2   17     3
#3   18     3
#4    5     1
#5    5     1
#6   22     4

或其他选项foverlaps来自data.table

library(data.table)
dfN <- data.table(index = seq_len(nrow(df2)), start = df2$time, end = df2$time)
setDT(df1)
setkey(dfN, start, end)
setkey(df1, start, end)
foverlaps(dfN, df1, which = TRUE)[, yid[match(xid, dfN$index)]]
#[1] 2 3 3 1 1 4

由于OP评论使用管道解决方案,@ Jilber Urbina的解决方案可以通过tidyverse函数实现

library(tidyverse)
df1 %>% 
    select(from = start, to = end) %>% 
    pmap(seq) %>% 
    do.call(cbind, .) %>% 
    list(.) %>%
    mutate(df2, new = ., 
                ind = map2(time, new, ~ which(.x == .y, arr.ind = TRUE)[,2])) %>%
    select(-new)
#   time ind
#1   11   2
#2   17   3
#3   18   3
#4    5   1
#5    5   1
#6   22   4