汇总条件语句

时间:2016-07-14 17:49:20

标签: r conditional aggregate

我试图在没有复杂的子集和/或逐行迭代的情况下找到问题的优雅解决方案。我将通过例子解释:

# Load data
df1 <- mtcars

# Can aggregate with simple math functions i.e. mean or sum
hp_by_cyl <- aggregate(hp ~ cyl, data=df1, mean)
> hp_by_cyl
  cyl        hp
1   4  82.63636
2   6 122.28571
3   8 209.21429

确定。但是,在我真正更复杂的数据中,我希望聚合一个逻辑值 - 即如果属于类别A的任何行的x为真,则y = 1。因此,为了扩展我的示例,我可以使用逻辑变量创建一个列:

df1$logic <- ifelse(df1$gear==4 & df1$hp < 150, 1, 0)
# How do I aggregate the logical values levels of cyl to answer yes/no
# if any car with x cylinders has 4 gears and < 150 hp ?
# So I want an finished table like this:
cyl     logic
4       1
6       1
8       0

所以我的问题是如何使用聚合(或替代)命令生成这样的表?即组合逻辑状态,而不是数值?

我还需要在实际中处理编码的缺失值,以便模拟这种复杂性,我将制作其中一个逻辑99:

df1[5, ]$logic <- 99

如果对于给定级别的cyl,一个值为1,则可以忽略99 - 如果其他所有其他值都为0,则聚合应为99。

道歉,如果有一个简单的答案我不会在我的真实数据中看到它似乎令人生畏。我可以解决一个讨厌的解决方案,但我知道它会非常慢,我有一个14000 X 140大小的数据集。在此先感谢所有。

2 个答案:

答案 0 :(得分:2)

我认为这就是你想要的:

aggregate(hp~cyl,data=mtcars,function(x) ifelse(mean(x)<150,1,0))

编辑: dplyr是你的朋友:

mtcars %>% group_by_(~cyl) %>% summarise_(logic=~ifelse(mean(hp)<150 & sum(wt)>3,1,0))

这有一个更复杂的逻辑陈述,所以希望这会有所帮助。如果您希望一次处理2个以上的变量,aggregate不是最佳方法。

答案 1 :(得分:1)

首先,不要打扰0/1/99,只需将其保留为TRUE / FALSE / NA。

df1$logic <- df1$gear==4 & df1$hp < 150

然后只与anytapply汇总。

aggregate(logic ~ cyl, data=df1, any)
##   cyl logic
## 1   4  TRUE
## 2   6  TRUE
## 3   8 FALSE

with(df1, tapply(logic, cyl, any))
##    4     6     8 
## TRUE  TRUE FALSE 

plyr包,特别是ddply函数,是许多人发现更直观的另一种选择。

library(plyr)
ddply(df1, ~cyl, summarize, isany = any(gear==4 & hp < 150))
##  cyl isany
## 1   4  TRUE
## 2   6  TRUE
## 3   8 FALSE