在R中根据时间排序后,如何计算具有最小值的行与后续行之间的差异?
how to calculate differences between the row with minimum value and the subsequent rows after sorting them according to time in R?
我有一个由以下代码给出的数据集。我正在寻找上升前具有最低值的行与按时间排列后每个 ID 的后续值之间的差异。
df <- data.frame(ID = c(1,1,1,1,1,2,2,2,3,3,3,3,3,3), time=c(6,12,18,24,30,3,9,21,6,12,18,24,30,36), value = c(0.9,0.7,2.8,3.8,0.5,1.3,3.1,0.8,1.2,0.6,3.7,1.8,0.9,0.3))
所以对于 ID 1,我想找出 0.7 和后续行之间的区别。我要的整体数据是这样的
df1 <- df%>%mutate(value.diff = c(NA, 0, 2.1, 3.1, -0.2, 0, 1.8, 0.5, NA, 0, 3.1, 1.2, 0.3, -0.3))
我应用了以下代码
df <- df[order(df$ID,df$time),]
df <- df%>%group_by(ID)%>%mutate(value.diff = diff(value-min(value)))
但这并没有达到目的。在这方面,我将不胜感激。
library(dplyr)
df %>%
group_by(ID) %>%
mutate(
ind = which.max(c(diff(value) > 0, TRUE)),
value.diff = replace(value - value[ind[1]], row_number() < ind, NA_real_)
) %>%
ungroup() %>%
select(-ind)
# # A tibble: 14 x 4
# ID time value value.diff
# <dbl> <dbl> <dbl> <dbl>
# 1 1 6 0.9 NA
# 2 1 12 0.7 0
# 3 1 18 2.8 2.10
# 4 1 24 3.8 3.10
# 5 1 30 0.5 -0.200
# 6 2 3 1.3 0
# 7 2 9 3.1 1.8
# 8 2 21 0.8 -0.5
# 9 3 6 1.2 NA
# 10 3 12 0.6 0
# 11 3 18 3.7 3.1
# 12 3 24 1.8 1.2
# 13 3 30 0.9 0.3
# 14 3 36 0.3 -0.3
解释:
ind
表示第一个增加的行(每个 ID
);这对于组内的所有行都是相同的值,因此在这方面效率有点低,但很有用;
value[ind[1]]
是第一个低点的值;我选择使用 value[ind[1]]
因为我们只需要 ind
索引之一来获得 value
的一个值,但是 value[ind]
也可以工作;
- 在
replace(.,.,.)
中,第一个是返回的默认值,value-value[ind[1]]
;第二个是指示默认值异常的条件,在本例中为“低点之前的行”;第三个是重置值,NA_real_
。我本可以同样轻松地使用 NA
,但我通常更喜欢声明我期望的 NA
版本;如果两个 yes/no 对象的 class 不完全相同,并且由于 class(NA)
是 logical
,一些工具如 dplyr::if_else
和 data.table::fifelse
将会出错,我选择了绝配。 (NA
有六种以上,仅供参考。)这在replace
中并不是严格要求的。另一个 fyi,我通常更喜欢 replace
,因为它更安全,并且在不简单时不会抹杀 class
(参见 How to prevent ifelse() from turning Date objects into numeric objects)。
我有一个由以下代码给出的数据集。我正在寻找上升前具有最低值的行与按时间排列后每个 ID 的后续值之间的差异。
df <- data.frame(ID = c(1,1,1,1,1,2,2,2,3,3,3,3,3,3), time=c(6,12,18,24,30,3,9,21,6,12,18,24,30,36), value = c(0.9,0.7,2.8,3.8,0.5,1.3,3.1,0.8,1.2,0.6,3.7,1.8,0.9,0.3))
所以对于 ID 1,我想找出 0.7 和后续行之间的区别。我要的整体数据是这样的
df1 <- df%>%mutate(value.diff = c(NA, 0, 2.1, 3.1, -0.2, 0, 1.8, 0.5, NA, 0, 3.1, 1.2, 0.3, -0.3))
我应用了以下代码
df <- df[order(df$ID,df$time),]
df <- df%>%group_by(ID)%>%mutate(value.diff = diff(value-min(value)))
但这并没有达到目的。在这方面,我将不胜感激。
library(dplyr)
df %>%
group_by(ID) %>%
mutate(
ind = which.max(c(diff(value) > 0, TRUE)),
value.diff = replace(value - value[ind[1]], row_number() < ind, NA_real_)
) %>%
ungroup() %>%
select(-ind)
# # A tibble: 14 x 4
# ID time value value.diff
# <dbl> <dbl> <dbl> <dbl>
# 1 1 6 0.9 NA
# 2 1 12 0.7 0
# 3 1 18 2.8 2.10
# 4 1 24 3.8 3.10
# 5 1 30 0.5 -0.200
# 6 2 3 1.3 0
# 7 2 9 3.1 1.8
# 8 2 21 0.8 -0.5
# 9 3 6 1.2 NA
# 10 3 12 0.6 0
# 11 3 18 3.7 3.1
# 12 3 24 1.8 1.2
# 13 3 30 0.9 0.3
# 14 3 36 0.3 -0.3
解释:
ind
表示第一个增加的行(每个ID
);这对于组内的所有行都是相同的值,因此在这方面效率有点低,但很有用;value[ind[1]]
是第一个低点的值;我选择使用value[ind[1]]
因为我们只需要ind
索引之一来获得value
的一个值,但是value[ind]
也可以工作;- 在
replace(.,.,.)
中,第一个是返回的默认值,value-value[ind[1]]
;第二个是指示默认值异常的条件,在本例中为“低点之前的行”;第三个是重置值,NA_real_
。我本可以同样轻松地使用NA
,但我通常更喜欢声明我期望的NA
版本;如果两个 yes/no 对象的 class 不完全相同,并且由于class(NA)
是logical
,一些工具如dplyr::if_else
和data.table::fifelse
将会出错,我选择了绝配。 (NA
有六种以上,仅供参考。)这在replace
中并不是严格要求的。另一个 fyi,我通常更喜欢replace
,因为它更安全,并且在不简单时不会抹杀class
(参见 How to prevent ifelse() from turning Date objects into numeric objects)。