【问题标题】:Creating new columns based on selected columns that calculates the ratio by group基于按组计算比率的选定列创建新列
【发布时间】:2023-04-08 07:58:01
【问题描述】:

我的数据如下:

DF <- structure(list(No_Adjusted_Gross_Income = structure(c(1L, 1L, 
    2L, 2L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), 
    NoR_from_1_to_5000 = c(1035373, 4272260, 1124098, 1035373, 
    4272260, 1124098), NoR_from_5000_to_10000 = c(319540, 4826042, 
    1959866, 319540, 4826042, 1959866), AGI_from_1_to_5000 = c(2588950186.5, 
    10682786130, 2810807049, 2588950186.5, 10682786130, 2810807049
    ), AGI_from_5000_to_10000 = c(2396550000, 36195315000, 14698995000, 
    2396550000, 36195315000, 14698995000)), class = "data.frame", row.names = c(NA, 
    -6L))

vn <- c("sum1", "sum2", "sum3", "sum4")

  No_Adjusted_Gross_Income NoR_from_1_to_5000 NoR_from_5000_to_10000 AGI_from_1_to_5000 AGI_from_5000_to_10000
1                        A            1035373                 319540         2588950187             2396550000
2                        A            4272260                4826042        10682786130            36195315000
3                        B            1124098                1959866         2810807049            14698995000
4                        B            1035373                 319540         2588950187             2396550000
5                        C            4272260                4826042        10682786130            36195315000
6                        C            1124098                1959866         2810807049            14698995000

对于第 2 到 5 列中的每一列,我想创建一个新列,它的值是原始值,除以值的总和除以 No_Adjusted_Gross_Income

我首先尝试了总和:

DF[, (vn) := as.data.table ( t( t( DF[, 2:5, by=c("No_Adjusted_Gross_Income")] )) ) ][]

但我得到一个错误:

Error in `:=`((vn), as.data.table(t(t(DF[, 2:5, by = c("No_Adjusted_Gross_Income")])))) : 
  Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").

我应该如何正确地做到这一点?我可以直接将原始列的值除以这个总和吗?

总和的期望输出:

DF <- setDT(DF)[, sum_1 := sum(NoR_from_1_to_5000),by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, sum_2 := sum(NoR_from_5000_to_10000),by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, sum_3 := sum(AGI_from_1_to_5000),by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, sum_4 := sum(AGI_from_5000_to_10000),by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, rat_1 := NoR_from_1_to_5000/sum_1 ,by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, rat_2 := NoR_from_5000_to_10000/sum_2 ,by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, rat_3 := AGI_from_1_to_5000/sum_3,by=c("No_Adjusted_Gross_Income")]
DF <- setDT(DF)[, rat_4 := AGI_from_5000_to_10000/sum_4,by=c("No_Adjusted_Gross_Income")]

   No_Adjusted_Gross_Income NoR_from_1_to_5000 NoR_from_5000_to_10000 AGI_from_1_to_5000 AGI_from_5000_to_10000   sum_1   sum_2       sum_3       sum_4 rat_1 rat_2 rat_3
1:                        A            1035373                 319540         2588950187             2396550000 5307633 5145582 13271736317 38591865000  0.20 0.062  0.20
2:                        A            4272260                4826042        10682786130            36195315000 5307633 5145582 13271736317 38591865000  0.80 0.938  0.80
3:                        B            1124098                1959866         2810807049            14698995000 2159471 2279406  5399757236 17095545000  0.52 0.860  0.52
4:                        B            1035373                 319540         2588950187             2396550000 2159471 2279406  5399757236 17095545000  0.48 0.140  0.48
5:                        C            4272260                4826042        10682786130            36195315000 5396358 6785908 13493593179 50894310000  0.79 0.711  0.79
6:                        C            1124098                1959866         2810807049            14698995000 5396358 6785908 13493593179 50894310000  0.21 0.289  0.21
   rat_4
1: 0.062
2: 0.938
3: 0.860
4: 0.140
5: 0.711
6: 0.289

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    如果您使用setDT(DF)[,....]data.frame 转换为data.table,您的代码确实可以计算总和 如果你只是想要这个比例,这可能就是你所追求的

    setDT(DF)[,paste0("rat_",1:4) :=lapply(.SD, function (x) round(x/sum(x),3)),
    .SDcols = 2:5,
    by =.(No_Adjusted_Gross_Income)][]
    

    【讨论】:

      【解决方案2】:

      这是我要做的事情......

      library( data.table )
      #colnames for the ratio
      rn <- c("rat_1", "rat_2", "rat_3", "rat_4")
      #make DF a data.table
      setDT( DF )
      #calculate the sum-columns by No_Adjusted_Gross_Income
      DF[, (vn) := lapply( .SD, sum, na.rm = TRUE ), by = .(No_Adjusted_Gross_Income), .SDcols = patterns( "^NoR|^AGI") ]
      #calculate the ratio by simple dividion of two data.tables
      DF[, (rn) := DF[, .SD, .SDcols = patterns("^NoR|^AGI")] / DF[, .SD, .SDcols = patterns("^sum")] ]
      
      #    No_Adjusted_Gross_Income NoR_from_1_to_5000 NoR_from_5000_to_10000 AGI_from_1_to_5000 AGI_from_5000_to_10000
      # 1:                        A            1035373                 319540         2588950187             2396550000
      # 2:                        A            4272260                4826042        10682786130            36195315000
      # 3:                        B            1124098                1959866         2810807049            14698995000
      # 4:                        B            1035373                 319540         2588950187             2396550000
      # 5:                        C            4272260                4826042        10682786130            36195315000
      # 6:                        C            1124098                1959866         2810807049            14698995000
      #       sum1    sum2        sum3        sum4     rat_1      rat_2     rat_3      rat_4
      # 1: 5307633 5145582 13271736317 38591865000 0.1950725 0.06209988 0.1950725 0.06209988
      # 2: 5307633 5145582 13271736317 38591865000 0.8049275 0.93790012 0.8049275 0.93790012
      # 3: 2159471 2279406  5399757236 17095545000 0.5205432 0.85981436 0.5205432 0.85981436
      # 4: 2159471 2279406  5399757236 17095545000 0.4794568 0.14018564 0.4794568 0.14018564
      # 5: 5396358 6785908 13493593179 50894310000 0.7916932 0.71118589 0.7916932 0.71118589
      # 6: 5396358 6785908 13493593179 50894310000 0.2083068 0.28881411 0.2083068 0.28881411
      

      【讨论】:

        【解决方案3】:

        正如my other answer 对OP 的相关问题Using lapply to create new columns based on old columns 中的解释,我建议以整洁的格式 存储和处理数据,其中每个观察值对应一行,每个变量对应一列。

        将提供的数据集重塑为长格式

        library(data.table)
        cols <- c("NoR", "AGI")
        long <- melt(setDT(DF), measure.vars = patterns(cols), variable.name = "range", value.name = cols)
        library(magrittr) # piping used to improve readability
        rn <- names(DF) %>% stringr::str_subset("from") %>% stringr::str_remove("^.*(?=from)") %>% unique
        long[, range := factor(range, labels = rn)]
        long
        
            No_Adjusted_Gross_Income              range     NoR         AGI
         1:                        A     from_1_to_5000 1035373  2588950187
         2:                        A     from_1_to_5000 4272260 10682786130
         3:                        B     from_1_to_5000 1124098  2810807049
         4:                        B     from_1_to_5000 1035373  2588950187
         5:                        C     from_1_to_5000 4272260 10682786130
         6:                        C     from_1_to_5000 1124098  2810807049
         7:                        A from_5000_to_10000  319540  2396550000
         8:                        A from_5000_to_10000 4826042 36195315000
         9:                        B from_5000_to_10000 1959866 14698995000
        10:                        B from_5000_to_10000  319540  2396550000
        11:                        C from_5000_to_10000 4826042 36195315000
        12:                        C from_5000_to_10000 1959866 14698995000
        

        提供的数据集包含多组同时重塑的度量列。从OP's previous question 中提供的更简单的数据集开始会更容易。

        附加每组的比率

        rat_cols <- paste0("rat_", cols)
        long[,  (rat_cols) := lapply(.SD, function(x) x / sum(x)), .SDcols = cols, by = .(No_Adjusted_Gross_Income, range)]
        long
        
            No_Adjusted_Gross_Income              range     NoR         AGI    rat_NoR    rat_AGI
         1:                        A     from_1_to_5000 1035373  2588950187 0.19507246 0.19507246
         2:                        A     from_1_to_5000 4272260 10682786130 0.80492754 0.80492754
         3:                        B     from_1_to_5000 1124098  2810807049 0.52054323 0.52054323
         4:                        B     from_1_to_5000 1035373  2588950187 0.47945677 0.47945677
         5:                        C     from_1_to_5000 4272260 10682786130 0.79169321 0.79169321
         6:                        C     from_1_to_5000 1124098  2810807049 0.20830679 0.20830679
         7:                        A from_5000_to_10000  319540  2396550000 0.06209988 0.06209988
         8:                        A from_5000_to_10000 4826042 36195315000 0.93790012 0.93790012
         9:                        B from_5000_to_10000 1959866 14698995000 0.85981436 0.85981436
        10:                        B from_5000_to_10000  319540  2396550000 0.14018564 0.14018564
        11:                        C from_5000_to_10000 4826042 36195315000 0.71118589 0.71118589
        12:                        C from_5000_to_10000 1959866 14698995000 0.28881411 0.28881411
        

        重塑为宽格式

        恕我直言,这仅在以宽格式(“Excel 样式”)呈现/打印数据时需要。对于后续处理,特别是绘图,我建议将数据保留为长格式(“SQL 样式”)。

        dcast(long, No_Adjusted_Gross_Income + rowid(No_Adjusted_Gross_Income, range) ~ range, 
              value.var = c(cols, rat_cols))
        
           No_Adjusted_Gross_Income No_Adjusted_Gross_Income_1 NoR_from_1_to_5000 NoR_from_5000_to_10000
        1:                        A                          1            1035373                 319540
        2:                        A                          2            4272260                4826042
        3:                        B                          1            1124098                1959866
        4:                        B                          2            1035373                 319540
        5:                        C                          1            4272260                4826042
        6:                        C                          2            1124098                1959866
           AGI_from_1_to_5000 AGI_from_5000_to_10000 rat_NoR_from_1_to_5000 rat_NoR_from_5000_to_10000
        1:         2588950187             2396550000              0.1950725                 0.06209988
        2:        10682786130            36195315000              0.8049275                 0.93790012
        3:         2810807049            14698995000              0.5205432                 0.85981436
        4:         2588950187             2396550000              0.4794568                 0.14018564
        5:        10682786130            36195315000              0.7916932                 0.71118589
        6:         2810807049            14698995000              0.2083068                 0.28881411
           rat_AGI_from_1_to_5000 rat_AGI_from_5000_to_10000
        1:              0.1950725                 0.06209988
        2:              0.8049275                 0.93790012
        3:              0.5205432                 0.85981436
        4:              0.4794568                 0.14018564
        5:              0.7916932                 0.71118589
        6:              0.2083068                 0.28881411
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-06-14
          • 1970-01-01
          • 2013-05-04
          • 2020-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多