【问题标题】:How can I create multiple columns at once using R, preferably dplyr or data.table?如何使用 R 一次创建多个列,最好是 dplyr 或 data.table?
【发布时间】:2020-04-27 10:07:39
【问题描述】:

我想根据数据框现有列中的值创建多个新变量。

这是我的数据的简化版本:

df <- structure(list(City = structure(c(5L, 4L, 4L, 3L, 1L, 2L), .Label = c("Chico", 
"Lawndale", "Los Angeles", "San Francisco", "San Jose"), class = "factor"), 
    yq = c("20071", "20111", "20074", "20124", "20111", "20124"
    ), cyq_total = c(15582L, 33668L, 40848L, 89028L, 1069L, 178L
    )), row.names = c(NA, -6L), class = "data.frame")
           City    yq cyq_total
1      San Jose 20071     15582
2 San Francisco 20111     33668
3 San Francisco 20074     40848
4   Los Angeles 20124     89028
5         Chico 20111      1069
6      Lawndale 20124       178

变量 cyq_total 表示一个城市在一年季度 (yq) 中的职位空缺数量。我想创建名为“Vac20071”、“Vac20111”等的新变量,其中值是给定城市给定年份和季度的 cyq_total。

这对我的示例进行了简化,但基本上我希望 Vac20071 列显示每个城市在 20071 年季度有多少空缺。对于其他年度季度也是如此。

期望的输出:

  City          yq    cyq_total Vac20071 Vac20111 Vac20074 Vac20124
  <fct>         <chr>     <int>    <dbl>    <dbl>    <dbl>    <dbl>
1 San Jose      20071     15582    15582        0        0        0
2 San Francisco 20111     33668        0    33668    40848        0
3 San Francisco 20074     40848        0    33668    40848        0
4 Los Angeles   20124     89028        0        0        0    89028
5 Chico         20111      1069        0     1069        0        0
6 Lawndale      20124       178        0        0        0      178

我必须执行此操作的代码有效,但效率不高。我正在寻找一种更好的方法来生成相同的结果,而不是复制/粘贴相同的代码并稍作更改:

df <- df %>% group_by(City) %>% mutate(Vac20071 = max(ifelse(yq == '20071', cyq_total, 0)))
df <- df %>% group_by(City) %>% mutate(Vac20111 = max(ifelse(yq == '20111', cyq_total, 0)))
df <- df %>% group_by(City) %>% mutate(Vac20074 = max(ifelse(yq == '20074', cyq_total, 0)))
df <- df %>% group_by(City) %>% mutate(Vac20124 = max(ifelse(yq == '20124', cyq_total, 0)))
df <- df %>% group_by(City) %>% mutate(Vac20111 = max(ifelse(yq == '20111', cyq_total, 0)))

【问题讨论】:

    标签: r dplyr data.table


    【解决方案1】:

    您可以获取宽格式的数据,然后加入。

    library(dplyr)
    library(tidyr)
    
    df %>%
     pivot_wider(names_from = yq, values_from = cyq_total, names_prefix = 'Vac') %>%
     left_join(df, by = 'City')
    
    # A tibble: 6 x 7
    #  City          Vac20071 Vac20111 Vac20074 Vac20124 yq    cyq_total
    #  <fct>            <int>    <int>    <int>    <int> <chr>     <int>
    #1 San Jose         15582       NA       NA       NA 20071     15582
    #2 San Francisco       NA    33668    40848       NA 20111     33668
    #3 San Francisco       NA    33668    40848       NA 20074     40848
    #4 Los Angeles         NA       NA       NA    89028 20124     89028
    #5 Chico               NA     1069       NA       NA 20111      1069
    #6 Lawndale            NA       NA       NA      178 20124       178
    

    @chinsoon12 建议的data.table 中的等效方法

    library(data.table)
    
    setDT(df)
    dcast(df,City ~ paste0("Vac", yq), value.var="cyq_total", fill=0L)[df, on=.(City)]
    

    【讨论】:

      【解决方案2】:

      使用带有矩阵数字索引的data.table 的选项:

      cols <- paste0("Vac", unique(df$yq))
      setDT(df)[, (cols) := 0L]
      df[, (cols) := {
          m <- as.matrix(.SD)
          ix <- match(paste0("Vac", yq), cols)
          m[cbind(rep(1L:.N, each=length(ix)), rep(ix, .N))] <- cyq_total
          as.data.table(m)
      }, City, .SDcols=cols]
      df
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-14
        • 1970-01-01
        • 2021-05-21
        • 1970-01-01
        • 1970-01-01
        • 2023-01-29
        • 1970-01-01
        • 2017-02-22
        相关资源
        最近更新 更多