计算“组特征”而不使用ddply和merge

ev7lccsx  于 2022-12-06  发布在  其他
关注(0)|答案(5)|浏览(115)

我想知道是否有一种更直接的方法来计算某种类型的变量比我通常采取的方法。
下面的示例可能最好地解释了这一点。(水果和水果是否腐烂)。我想在每一行中添加同一类别腐烂水果的百分比。例如,苹果有4个条目,其中2个腐烂,因此apple的每一行都应该读作0.5。目标值(纯粹作为说明)包含在“期望的结果”列中。
我以前通过 * 在fruit变量上使用“ddply”命令(以sum/lenght作为函数),创建一个新的3*2 Dataframe *,使用“merge”命令将这些值链接回旧的 Dataframe 来解决这个问题。
这感觉像是一个迂回的方法,我想知道是否有更好/更快的方法来做这件事!理想的是一个通用的方法,这是很容易调整的,如果一个而不是百分比需要确定是否所有的水果是腐烂的,任何水果是腐烂的,等等等等....
非常感谢你
W型

Fruit Rotten Desired_Outcome_PercRotten
1   Apple      1                        0.5
2   Apple      1                        0.5
3   Apple      0                        0.5
4   Apple      0                        0.5
5    Pear      1                       0.75
6    Pear      1                       0.75
7    Pear      1                       0.75
8    Pear      0                       0.75
9  Cherry      0                          0
10 Cherry      0                          0
11 Cherry      0                          0

#create example datagram; desired outcome columns are purely inserted as illustrative of target outcomes
Fruit=c(rep("Apple",4),rep("Pear",4),rep("Cherry",3))
Rotten=c(1,1,0,0,1,1,1,0,0,0,0)
Desired_Outcome_PercRotten=c(0.5,0.5,0.5,0.5,0.75,0.75,0.75,0.75,0,0,0)
df=as.data.frame(cbind(Fruit,Rotten,Desired_Outcome_PercRotten))        
df
t40tm48m

t40tm48m1#

只需使用ddplymutate即可实现此操作:

# changed summarise to transform on joran's suggestion
# changed transform to mutate on mnel's suggestion :)
ddply(df, .(Fruit), mutate, Perc = sum(Rotten)/length(Rotten))

#     Fruit Rotten Perc
# 1   Apple      1 0.50
# 2   Apple      1 0.50
# 3   Apple      0 0.50
# 4   Apple      0 0.50
# 5  Cherry      0 0.00
# 6  Cherry      0 0.00
# 7  Cherry      0 0.00
# 8    Pear      1 0.75
# 9    Pear      1 0.75
# 10   Pear      1 0.75
# 11   Pear      0 0.75
wsxa1bj1

wsxa1bj12#

data.table是超快的,因为它通过引用更新。使用它怎么样?

library(data.table)

dt=data.table(Fruit,Rotten,Desired_Outcome_PercRotten)

dt[,test:=sum(Rotten)/.N,by="Fruit"]
#dt
#     Fruit Rotten Desired_Outcome_PercRotten test
# 1:  Apple      1                       0.50 0.50
# 2:  Apple      1                       0.50 0.50
# 3:  Apple      0                       0.50 0.50
# 4:  Apple      0                       0.50 0.50
# 5:   Pear      1                       0.75 0.75
# 6:   Pear      1                       0.75 0.75
# 7:   Pear      1                       0.75 0.75
# 8:   Pear      0                       0.75 0.75
# 9: Cherry      0                       0.00 0.00
#10: Cherry      0                       0.00 0.00
#11: Cherry      0                       0.00 0.00
h79rfbju

h79rfbju3#

一个以R为底的解决方案是使用ave

within(df, {
  ## Because of how you've created your data.frame
  ##   Rotten is actually a factor. So, we need to
  ##   convert it to numeric before we can use mean
  Rotten <- as.numeric(as.character(Rotten))
  NewCol <- ave(Rotten, Fruit)
})
    Fruit Rotten Desired_Outcome_PercRotten NewCol
1   Apple      1                        0.5   0.50
2   Apple      1                        0.5   0.50
3   Apple      0                        0.5   0.50
4   Apple      0                        0.5   0.50
5    Pear      1                       0.75   0.75
6    Pear      1                       0.75   0.75
7    Pear      1                       0.75   0.75
8    Pear      0                       0.75   0.75
9  Cherry      0                          0   0.00
10 Cherry      0                          0   0.00

或更短:

transform(df, desired = ave(Rotten == 1, Fruit))

ave应用的默认函数是mean,因此我没有在这里包括它。但是,如果你想做一些不同的事情,你可以通过附加FUN = some-function-here来指定一个不同的函数。

bgibtngc

bgibtngc4#

由于ave已经存在,让我使用我选择的基R函数添加一个解决方案:aggregate .
您可以通过以下方式获得所需数据:

aggregate(as.numeric(as.character(Rotten)) ~ Fruit, df, mean)

但是,您需要在之后仍然merge它(或在一块):

merge(df, aggregate(as.numeric(as.character(Rotten)) ~ Fruit, df, mean))
vyu0f0g1

vyu0f0g15#

使用dplyr-
对于dplyr版本1.1.0及更高版本-

library(dplyr)

df %>% mutate(Result = sum(Rotten)/n(), .by = Fruit)

#    Fruit Rotten Desired_Outcome_PercRotten Result
#1   Apple      1                       0.50   0.50
#2   Apple      1                       0.50   0.50
#3   Apple      0                       0.50   0.50
#4   Apple      0                       0.50   0.50
#5    Pear      1                       0.75   0.75
#6    Pear      1                       0.75   0.75
#7    Pear      1                       0.75   0.75
#8    Pear      0                       0.75   0.75
#9  Cherry      0                       0.00   0.00
#10 Cherry      0                       0.00   0.00
#11 Cherry      0                       0.00   0.00

使用.by参数可提供临时分组,并避免使用group_byungroup语句。
对于dplyr版本〈1.1.0

df %>%
  group_by(Fruit) %>%
  mutate(Result = sum(Rotten)/n()) %>%
  ungroup

数据

df <-  data.frame(Fruit,Rotten,Desired_Outcome_PercRotten)

相关问题