代码之家  ›  专栏  ›  技术社区  ›  user1885116

在没有ddply和合并的情况下计算“组特征”

  •  7
  • user1885116  · 技术社区  · 11 年前

    我想知道是否有比我通常采用的方法更直接的方法来计算某种类型的变量。。。。

    下面的例子可能解释得最好。我有一个有2列的数据框架(水果和水果是否腐烂)。我想为每一行添加例如同一类别水果腐烂的百分比。例如,苹果有4个条目,其中2个已经腐烂,所以苹果的每行应该读0.5。目标值(纯粹是为了说明)包含在“期望结果”列中。

    我之前曾通过 *在fruit变量上使用“ddply”命令(使用sum/lenght作为函数),创建一个新的3*2数据帧 *使用“merge”命令将这些值链接回旧的数据帧。

    这感觉像是一种迂回的方式,我想知道是否有更好/更快的方式!理想情况下,这是一种通用方法,如果需要确定是否所有水果都腐烂,任何水果都腐烂等,而不是百分比,则很容易调整。。。。

    非常感谢,

    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
    
    5 回复  |  直到 11 年前
        1
  •  11
  •   Arun    11 年前

    你只需要 ddply mutate :

    # 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
    
        2
  •  10
  •   thelatemail    11 年前

    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
    
        3
  •  5
  •   G. Grothendieck    11 年前

    以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))
    

    应用的默认函数 大道 mean ,所以我没有把它包括在这里。但是,您可以通过附加 FUN = some-function-here 如果你想做一些不同的事情。

        4
  •  2
  •   Henrik    11 年前

    ave 已经出来了,让我使用我选择的基本R函数添加一个解决方案: aggregate .

    您只需使用以下工具即可获得所需的数据:

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

    然而,你仍然需要 merge 之后(或整体):

    merge(df, aggregate(as.numeric(as.character(Rotten)) ~ Fruit, df, mean))
    
        5
  •  0
  •   Ronak Shah    2 年前

    使用 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_by ungroup 声明。

    对于 dplyr公司 版本<1.1.0

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

    数据

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