【问题标题】:R: Subtract values from rows based on another columnR:从基于另一列的行中减去值
【发布时间】:2016-10-24 12:37:03
【问题描述】:

我有一个数据集如下:

Group    Type   Income
 A        X       1000
 A        Y       500
 B        Y       2000
 B        X       1500
 C        X       700
 D        Y       600

我需要输出如下:

Group    Diff
  A       500
  B      -500
  C       700
  D      -600

我能想到的一种方法是使用 X 和 Y 类型分隔数据,然后将不存在 X 或 Y 的组的收入添加为 0,然后合并数据,例如每个组都有一个名为 IncomeX 的列另一个名为 IncomeY,然后减去这两列。

有没有更简单的方法来做到这一点?

【问题讨论】:

    标签: r


    【解决方案1】:

    我会这样做:(使用dplyrreshape2 包)

    library("dplyr")
    library("reshape2")
    
    t <- read.table(text = "Group    Type   Income
     A        X       1000
                    A        Y       500
                    B        Y       2000
                    B        X       1500
                    C        X       700
                    D        Y       600", header = TRUE)
    
    t %>% 
        dcast(Group ~ Type, value.var = "Income", fill = 0) %>% 
        mutate(Diff = X - Y) %>% 
        select(Group, Diff)
    
    # Group Diff
    # 1     A  500
    # 2     B -500
    # 3     C  700
    # 4     D -600
    

    dcast 更改表格格式,mutate 创建新列。

    【讨论】:

      【解决方案2】:

      在基础 R 中试试这个:

      aggregate(Diff~Group, 
                with(df, data.frame(Group=Group, Diff=ifelse(Type=="X", 1, -1)*Income)), sum)
      
      # Group Diff
      #1     A    500
      #2     B   -500
      #3     C    700
      #4     D   -600
      

      数据

      df <- structure(list(Group = structure(c(1L, 1L, 2L, 2L, 3L, 4L), .Label = c("A", 
      "B", "C", "D"), class = "factor"), Type = structure(c(1L, 2L, 
      2L, 1L, 1L, 2L), .Label = c("X", "Y"), class = "factor"), Income = c(1000L, 
      500L, 2000L, 1500L, 700L, 600L)), .Names = c("Group", "Type", 
      "Income"), class = "data.frame", row.names = c(NA, -6L))
      

      【讨论】:

        【解决方案3】:

        我们可以使用data.table。将'data.frame'转换为'data.table'(setDT(df1)),对于'Type'即'Y',将'Income'转换为负值,然后按'Group'分组,得到sum的“收入”。

        library(data.table)
        setDT(df1)[Type == "Y", Income := -1 * Income][, .(Diff= sum(Income))  , Group] 
        #   Group Diff
        #1:     A  500
        #2:     B -500
        #3:     C  700
        #4:     D -600
        

        或者tidyr/dplyr

        library(dplyr)
        library(tidyr)
        spread(df1, Type, Income, fill = 0) %>%
                        transmute(Group, Diff = X- Y)
        #    Group Diff
        #1     A  500
        #2     B -500
        #3     C  700
        #4     D -600
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-22
          相关资源
          最近更新 更多