我想通过应用一个调用另一个数据帧的函数来改变数据帧。我可以用几种不同的方式实现这一点,但想知道如何“正确”地做到这一点。
以下是我正在尝试做的一个例子。我有一个数据帧有一些开始时间,第二个有一些定时观察。我想返回一个数据帧,其中包含开始时间,以及在开始时间之后某个窗口内发生的观察数。 e.g。
set.seed(1337)
df1 <- data.frame(id=LETTERS[1:3], start_time=1:3*10)
df2 <- data.frame(time=runif(100)*100)
lapply(df1$start_time, function(s) sum(df2$time>s & df2$time<(s+15)))
到目前为止我用dplyr得到的最好的是以下内容(但这会丢失身份变量):
df1 %>%
rowwise() %>%
do(count = filter(df2, time>.$start_time, time < (.$start_time + 15))) %>%
mutate(n=nrow(count))
输出:
Source: local data frame [3 x 2]
Groups: <by row>
# A tibble: 3 × 2
count n
<list> <int>
1 <data.frame [17 × 1]> 17
2 <data.frame [18 × 1]> 18
3 <data.frame [10 × 1]> 10
我原本希望能够做到这一点:
df1 <- data.frame(id=LETTERS[1:3], start_time=1:3*10)
df2 <- data.frame(time=runif(100)*100)
df1 %>%
group_by(id) %>%
mutate(count = nrow(filter(df2, time>start_time, time<(start_time+15))))
但这会返回错误:
Error: comparison (6) is possible only for atomic and list types
这样做的dplyr方式是什么?
答案 0 :(得分:3)
以下是data.table
的一个选项,我们可以使用non-equi
联接
library(data.table)#1.9.7+
setDT(df1)[, start_timeNew := start_time + 15]
setDT(df2)[df1, .(id, .N), on = .(time > start_time, time < start_timeNew),
by = .EACHI][, c('id', 'N'), with = FALSE]
# id N
#1: A 17
#2: B 18
#3: C 10
给出与OP的base R
方法
sapply(df1$start_time, function(s) sum(df2$time>s & df2$time<(s+15)))
#[1] 17 18 10
如果我们还需要'id'变量作为dplyr
中的输出,我们可以修改OP的代码
df1 %>%
rowwise() %>%
do(data.frame(., count = filter(df2, time>.$start_time,
time < (.$start_time + 15)))) %>%
group_by(id) %>%
summarise(n = n())
# id n
# <fctr> <int>
#1 A 17
#2 B 18
#3 C 10
或map
来自purrr
dplyr
library(purrr)
df1 %>%
split(.$id) %>%
map_df(~mutate(., N = sum(df2$time >start_time & df2$time < start_time + 15))) %>%
select(-start_time)
# id N
#1 A 17
#2 B 18
#3 C 10
答案 1 :(得分:2)
使用dplyr
的另一种略有不同的方法:
result <- df1 %>% group_by(id) %>%
summarise(count = length(which(df2$time > start_time &
df2$time < (start_time+15))))
print(result)
### A tibble: 3 x 2
## id count
## <fctr> <int>
##1 A 17
##2 B 18
##3 C 10
我相信您可以使用length
和which
来计算id
中每个df1
条件为真的出现次数。然后,按id
分组并将其用于summarise
。
如果每start_time
个id
可能更多,那么您可以使用相同的功能rowwise
和mutate
:
result <- df1 %>% rowwise() %>%
mutate(count = length(which(df2$time > start_time &
df2$time < (start_time+15))))
print(result)
##Source: local data frame [3 x 3]
##Groups: <by row>
##
### A tibble: 3 x 3
## id start_time count
## <fctr> <dbl> <int>
##1 A 10 17
##2 B 20 18
##3 C 30 10