我有一个包含数千条记录的数据框。我的数据框如下所示:
Row ID OBS Dist_cover
1 2 1 60
2 2 0 140
3 2 0 15
4 2 0 147
5 2 0 37
6 2 0 89
7 3 1 239
8 3 0 62
9 3 0 11
10 3 0 193
我需要在Dist_cover
的“ 1”和“ 0” OBS
值之间找到差异,但是按id
分组。本质上,我正在寻找[1,4]-[2,4],[1,4]-[3,4],[1,4]-[4,4],[1,4]之间的区别-[5,4],[1,4]-[6,4]和[7,4]-[8,4],[7,4]-[9,4],[7,4]-[ 10,4]等。我已经尝试过使用dplyr(突变)和data.base包的各种方法,但是仅弄清楚了如何运行连续的行,而无法弄清楚如何按id
进行分组。有什么想法吗?
答案 0 :(得分:4)
您可以使用ave
将Dist_cover
按ID
分组来完成所需的操作。
请注意,尽管该问题指出应按OBS
进行分组,但实际上并不需要。等于1的OBS
始终是第一个,就像在问题中隐式指出的那样。 OP希望“ [1,4]-[2,4],[1,4]-[3,4]等之间的差异”。。
ave(dat$Dist_cover, dat$ID, FUN = function(x) x - x[1])
#[1] 0 80 -45 87 -23 29 0 -177 -228 -46
数据。
dat <-
structure(list(Row = 1:10, ID = c(2L, 2L, 2L, 2L, 2L, 2L, 3L,
3L, 3L, 3L), OBS = c(1L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L),
Dist_cover = c(60L, 140L, 15L, 147L, 37L, 89L, 239L, 62L,
11L, 193L)), .Names = c("Row", "ID", "OBS", "Dist_cover"), class = "data.frame", row.names = c(NA,
-10L))
答案 1 :(得分:1)
按“ ID”分组后,对“ Dist_cover”进行子集设置,其中“ OBS”为1(假设每个ID的单个实例只有1个),将其从“ Dist_covert”中减去,然后filter
“ OBS”为0的值。
library(dplyr)
df1 %>%
group_by(ID) %>%
mutate(Diff = Dist_cover[OBS==1] - Dist_cover) %>%
# if OBS is 1 occurs always as the first observation for ID
# mutate(Diff = first(Dist_cover) - Dist_cover) %>%
filter(OBS == 0)
df1 <- structure(list(Row = 1:10, ID = c(2L, 2L, 2L, 2L, 2L, 2L, 3L,
3L, 3L, 3L), OBS = c(1L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L),
Dist_cover = c(60L, 140L, 15L, 147L, 37L, 89L, 239L, 62L,
11L, 193L)), .Names = c("Row", "ID", "OBS", "Dist_cover"),
class = "data.frame", row.names = c(NA,
-10L))