我试图将一列值附加到R列表的元素,其中每个元素的长度各不相同。这是一个示例列表foo:
A B C
1 1 150
1 2 25
1 4 30
2 1 200
2 3 15
3 4 30
首先,我将foo分解为foo,其元素基于A的每个唯一值。现在,我想写一个函数a)将A的每个值的C值相加,但是b)排除当B == 4时B.c)将总和作为新列D附加,并且d)C除以D以产生比例(列E)。最终,它将结合在一个新的df中,看起来像:
A B C D E
1 1 150 175 0.857
1 2 25 175 0.143
1 4 30 175 0.171
2 1 200 215 0.930
2 3 15 215 0.070
3 4 30 0 0/NA
但是,我遇到了问题,因为在某些情况下,对于给定的A值,只有B == 4(这里,A == 3)的情况,所以当我尝试将C除以D时,我收到错误消息。
有没有办法将if / else语句合并到函数中,这样当A是唯一的并且B的唯一可能值是4时,将跳过该操作并在附加列中放置一个默认的非零值?
将df子集设置为B == 4的排除情况使得后面的操作更加困难,但是包括B == 4使得总和/比例计算不准确的情况。
任何帮助表示赞赏!这是当前的代码:
goo <- lapply(foo,function(df){
df$D <- sum(df$C, na.rm = TRUE)
df$E <- df$C / df$D
### .....
df
})
答案 0 :(得分:4)
这是我如何使用dplyr
library(dplyr)
newfoo <- foo %>%
group_by(A) %>%
mutate(D = sum(C[B != 4]),
E = C/D)
#newfoo # the resulting data.frame
#Source: local data frame [6 x 5]
#Groups: A
#
# A B C D E
#1 1 1 150 175 0.85714286
#2 1 2 25 175 0.14285714
#3 1 4 30 175 0.17142857
#4 2 1 200 215 0.93023256
#5 2 3 15 215 0.06976744
#6 3 4 30 0 Inf
或者如果您想避免Inf
,可以像这样使用ifelse
:
newfoo <- foo %>%
group_by(A) %>%
mutate(D = sum(C[B != 4]),
E = ifelse(D == 0, 0, C/D))
#Source: local data frame [6 x 5]
#Groups: A
#
# A B C D E
#1 1 1 150 175 0.85714286
#2 1 2 25 175 0.14285714
#3 1 4 30 175 0.17142857
#4 2 1 200 215 0.93023256
#5 2 3 15 215 0.06976744
#6 3 4 30 0 0.00000000
答案 1 :(得分:4)
data.table
(可能)解决方案
library(data.table)
setDT(foo)[, D := sum(C[B != 4]), by = A][, E := C/D]
# foo
# A B C D E
# 1: 1 1 150 175 0.85714286
# 2: 1 2 25 175 0.14285714
# 3: 1 4 30 175 0.17142857
# 4: 2 1 200 215 0.93023256
# 5: 2 3 15 215 0.06976744
# 6: 3 4 30 0 Inf
在E
时,不确定要将哪些内容放入A == 3
列,但您可以使用is.finite
并避免弄乱ifelse
,例如(替换零)
setDT(foo)[, D := sum(C[B!=4]), by = A][, E := C/D][!is.finite(E), E := 0]
答案 2 :(得分:3)
以下是使用base
包的解决方案。
首先,如果已将A
转换为某个因素,请确保数据已正确建模:
df$A <- factor(df$A)
现在,我们可以使用D
来计算tapply
,t
会逐组迭代并将结果作为with
能够返回。我们执行此subset
df
B != 4
df$D <- with(subset(df, B != 4), tapply(C, A, sum))[df$A]
。
A
请注意,由于ifelse
是一个因素,我们可以索引到表中以执行合并。现在我们可以使用E
来计算df$E <- with(df, ifelse(is.na(D), 0, C/D))
:
{{1}}