首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >R:使用if/ with在具有不同长度的对象的列表中追加列

R:使用if/ with在具有不同长度的对象的列表中追加列
EN

Stack Overflow用户
提问于 2014-10-13 21:10:55
回答 3查看 1.8K关注 0票数 3

我试图在R列表的元素中追加一列值,其中每个元素都有不同的长度。下面是一个列表foo示例:

代码语言:javascript
运行
复制
A   B   C   
1   1   150
1   2   25
1   4   30
2   1   200
2   3   15
3   4   30

首先,我将foo分解为list foo,它的元素基于A的每个唯一值。现在,我想写一个函数: a) A的每个值的C和,但b)当B == 4. c时,不包括B)和作为一个新列D附加,d) C除以D得到一个比例(E列)。最终,它将合并到一个新的df中,如下所示:

代码语言:javascript
运行
复制
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使和/比例计算不准确的情况。

任何帮助都是非常感谢的!以下是当前代码:

代码语言:javascript
运行
复制
goo <- lapply(foo,function(df){
  df$D <- sum(df$C, na.rm = TRUE)
  df$E <- df$C / df$D
  ###  .....
  df
})
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-13 21:25:08

下面是我如何使用dplyr来做这件事

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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
票数 4
EN

Stack Overflow用户

发布于 2014-10-13 21:34:28

data.table (可能的)解决方案

代码语言:javascript
运行
复制
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

不确定A == 3时要将什么放入列A == 3,但可以使用is.finite来实现,并避免与ifelse混为一谈,例如(用0替换)

代码语言:javascript
运行
复制
setDT(foo)[, D := sum(C[B!=4]), by = A][, E := C/D][!is.finite(E), E := 0]
票数 4
EN

Stack Overflow用户

发布于 2014-10-14 00:42:03

下面是使用base包的解决方案。

首先,通过将A转换为一个因子(如果它还不是一个因子),确保对数据进行适当的建模:

代码语言:javascript
运行
复制
df$A <- factor(df$A)

现在,我们可以使用D来计算tapply,它迭代groupwise并将结果作为t来返回。我们这样做,withsubset of dfB != 4

代码语言:javascript
运行
复制
df$D <- with(subset(df, B != 4), tapply(C, A, sum))[df$A]

注意,由于A是一个因素,我们可以在表中索引以执行合并。现在我们可以使用ifelse计算E了。

代码语言:javascript
运行
复制
df$E <- with(df, ifelse(is.na(D), 0, C/D))
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26348929

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档