我有一个小问题。我正在研究数据框架。它如下:
df1
Duration Intensity
NA NA
10 0.1016
10 0.0254
NA NA
NA NA
10 0.0508
10 0.0508
10 0.1016
NA NA
10 0.0254
我想计算10分钟“持续时间”的每个事件的“强度”的累积总和。或者换句话说,我想在“强度”列中的每个“NA”值之间总结“强度”的值。输出应如下所示:
DF2
Duration Intensity Intensity_sum
NA NA
10 0.1016
10 0.0254 0.127
NA NA
NA NA
10 0.0508
10 0.0508
10 0.1016 0.2032
NA NA
10 0.0254 0.0254
我尝试了以下代码:
library(dplyr)
df2 <- as.data.frame(mutate(df1,Intensity_sum = with(df1,Duration==10,cumsum(Intensity))))
但我只收到TRUE或FALSE结果,而不是值。
答案 0 :(得分:2)
我们可以使用data.table
。转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT(df1)
),按逻辑向量(!is.na(Duration)
)的游程长度ID分组,我们指定(:=
)强度为sum
&#39 ; as&#39; Intensity_sum and later replace the
重复的元素与&#39; NA&#39;
library(data.table)
setDT(df1)[, Intensity_sum := sum(Intensity), rleid(!is.na(Duration))]
df1[duplicated(Intensity_sum, fromLast=TRUE), Intensity_sum := NA]
df1
# Duration Intensity Intensity_sum
# 1: NA NA NA
# 2: 10 0.1016 NA
# 3: 10 0.0254 0.1270
# 4: NA NA NA
# 5: NA NA NA
# 6: 10 0.0508 NA
# 7: 10 0.0508 NA
# 8: 10 0.1016 0.2032
# 9: NA NA NA
#10: 10 0.0254 0.0254
或者在一行中,我们可以按rleid
进行分组(如上所述)并通过复制NA
以及强度&#39的sum
来分配新列。 ;
setDT(df1)[, Intensity_sum := rep(c(NA,sum(Intensity)), c(.N-1, 1)), rleid(!is.na(Duration))]
答案 1 :(得分:0)
使用我在下面建议的第四种data.table
方法,可以在基数R中获得所需的结果。此方法使用ave
和replace
ave(df$Intensity, cumsum(is.na(df$Intensity)),
FUN=function(x) replace(NA, (seq_along(x) == length(x) & length(x) > 1),
sum(x, na.rm=TRUE)))
[1] NA NA 0.1270 NA NA NA NA 0.2032 NA 0.0254
以下是一些额外的data.table
选项
df[, val := ifelse(is.na(shift(Intensity, type="lead")),
sum(Intensity, na.rm=TRUE), NA), by=cumsum(is.na(Intensity))]
在这种情况下,使用cumsum
函数执行分组,并使用使用ifelse
检查NA边界的shift
执行求和的放置。
这有点慢,如果有一个带有相邻数值的NA值,则会加0而不是NA。可以修改ifelse
的第一个参数,这样就不会发生。
其次,使用c
和子集代替ifelse
的更快的解决方案。我添加了逻辑,以便单行NA接收和NA而不是0。
df[, val2 := c(NA, sum(Intensity, na.rm=TRUE))[(seq_len(.N) == .N &.N > 1) + 1],
by=cumsum(is.na(Intensity))]
稍微修改此方法以利用对NA
的喜爱操作。我们得到以下内容。
df[, val3 := sum(Intensity, na.rm=TRUE) * NA^(seq_len(.N) != .N | .N == 1),
by=cumsum(is.na(Intensity))]
此方法利用了NA^x
,其中x!= 0返回NA,但NA^0
返回1而NA^FALSE
等同于NA^0
。
第四种选择是使用replace
。此函数用指定索引处的值替换向量。
df[, val4 := replace(NA, (seq_len(.N) == .N & .N != 1),
sum(Intensity, na.rm=TRUE)),
by=cumsum(is.na(Intensity))]
这三种方法的结果如下所示。
df
Duration Intensity val3 val val2 val4
1: NA NA NA NA NA NA
2: 10 0.1016 NA NA NA NA
3: 10 0.0254 0.1270 0.1270 0.1270 0.1270
4: NA NA NA 0.0000 NA NA
5: NA NA NA NA NA NA
6: 10 0.0508 NA NA NA NA
7: 10 0.0508 NA NA NA NA
8: 10 0.1016 0.2032 0.2032 0.2032 0.2032
9: NA NA NA NA NA NA
10: 10 0.0254 0.0254 0.0254 0.0254 0.0254