【问题标题】:Using tidyverse, how can you generate new columns dynamically?使用 tidyverse,如何动态生成新列?
【发布时间】:2020-04-13 13:17:36
【问题描述】:

假设我有一个包含数十列的数据框,而我的自定义函数需要这些列中的每一列加上向量中的一个数字才能给我所需的输出。完成所有这些之后,我需要根据数据框中的原始列名生成新的列名。如何使用tidyverse 而不是for 循环或base R 中的其他解决方案来完成此操作。

MWE

structure(list(col1 = c(36.0520583373645, 37.9423749063706, 33.6806634587719, 
34.031649012457, 29.5448679963449, NA, 34.7576769718877, 30.484217745574, 
32.9849083643022, 27.4081694831058, 35.8624919654559, 35.0284347997991, 
NA, 32.112605893241, 27.819354948082, 35.6499532124921, 35.0265642403216, 
32.4006569441297, 30.3698557864842, 31.8229364456928, 34.3715903109276
), col2 = c(32.9691195198199, 35.6643664156284, 33.8748732989736, 
34.5436311813644, 33.2228201914256, 38.7621696867191, 34.8399804318992, 
32.9063078995457, 35.7391166214367, 32.7217251282669, 36.3039268989853, 
35.9607654868559, 33.1385915196435, 34.7987649028199, 33.7100463668523, 
34.7773403671057, 35.8592997980752, 33.8537127786535, 31.9106243803505, 
39.3099469314882, 35.1849826815196), col3 = c(33.272278716963, 
NA, 31.8594920410129, 33.1695042551974, 29.3800694974438, 35.1504378875245, 
34.0771487001433, 29.0162879030415, 30.6960024888799, 29.5542117965184, 
34.3726321365982, 36.0602274148362, 33.1207772548047, 31.5506876209822, 
28.8649303491974, 33.4598790144265, 30.5573454464747, 31.6026723913051, 
30.4716061556625, 33.009463000301, 30.846230953425)), row.names = c(NA, 
-21L), class = "data.frame")

将上面的数据保存在一个文件中,然后使用example <- dget(file.choose())读取上面的dataframe。

代码

y <- c (2, 1, 1.5)

customfun <- function(x, y){
  n  <- log (x) * y
  print (n)
}

df <- example %>%
  dplyr::mutate(col1.log = customfun (col1, y = y[1])) %>%
  dplyr::mutate(col2.log = customfun (col2, y = y[2])) %>%
  dplyr::mutate(col3.log = customfun (col3, y = y[3]))

问题

想象一下,我有几十个这样的列,而不仅仅是 MWE 中的 3 个,如何使用 tidyverse 动态生成新的列?

【问题讨论】:

    标签: r function dataframe dynamic tidyverse


    【解决方案1】:

    我们可以使用map2bind_cols 来添加新列

    library(dplyr)
    library(purrr)
    
    bind_cols(example, map2_df(example, y, customfun) %>%
                               rename_all(~paste0(., ".log"))) 
    
    #       col1     col2     col3 col1.log col2.log col3.log
    #1  36.05206 32.96912 33.27228 7.169928 3.495571 5.257087
    #2  37.94237 35.66437       NA 7.272137 3.574152       NA
    #3  33.68066 33.87487 31.85949 7.033848 3.522674 5.192003
    #4  34.03165 34.54363 33.16950 7.054582 3.542223 5.252446
    #...
    

    【讨论】:

    • 在咕噜声森林中写的好诗,我想知道 map2_df 与另一个邻居 map2_dfc 有什么不同,它似乎给出了类似的输出?
    • @doctorate 是的,在这种情况下,您可以使用 map2_df/map2_dfc/map2_dfr 中的任何一个,它会给出相同的输出。对list进行操作时输出不同。
    【解决方案2】:

    tidyverse 不适用于这些类似sweep() 的操作,但是,一种选择可能是:

    example %>%
     do(., sweep(., 2, FUN = customfun, y)) %>%
     rename_all(~ paste(., "log", sep = "."))
    
       col1.log col2.log col3.log
    1  7.169928 3.495571 5.257087
    2  7.272137 3.574152       NA
    3  7.033848 3.522674 5.192003
    4  7.054582 3.542223 5.252446
    5  6.771820 3.503237 5.070475
    6        NA 3.657445 5.339456
    7  7.096801 3.550766 5.292941
    8  6.834418 3.493664 5.051786
    9  6.992100 3.576246 5.136199
    10 6.621682 3.488039 5.079339
    

    【讨论】:

    • 是否可以保留原始列?
    • 我会说将列绑定为example %&gt;% do(., sweep(., 2, FUN = customfun, y)) %&gt;% rename_all(~ paste(., "log", sep = ".")) %&gt;% bind_cols(example) 更容易。
    • 好吧,我是有人会想出另一个答案!
    • @tmfmnk 你能帮忙解决这个问题吗stackoverflow.com/questions/59431981/…
    猜你喜欢
    • 2012-06-11
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多