【问题标题】:using dplyr to create new columns based on condition from data in R使用 dplyr 根据 R 中数据的条件创建新列
【发布时间】:2019-11-28 14:11:47
【问题描述】:

我正在尝试根据日期在我的数据中创建新列。

我想做的是获取以下格式的数据:

        dates  yes_no grp event    2017-01-02     2017-01-04
1  2017-01-01     364   1    NA       NA            NA
2  2017-01-02    2451   1     1        1            NA
3  2017-01-03   32440   1    NA       NA            NA
4  2017-01-04  234341   1     1       NA             1
5  2017-01-05  123443   1    NA       NA            NA
6  2017-01-01    7273   2    NA       NA            NA
7  2017-01-02    2331   2     1        1            NA
8  2017-01-03   12332   2    NA       NA            NA
9  2017-01-04   12233   2     1       NA             1
10 2017-01-05 1232323   2    NA       NA            NA

我有 2 个组 grp 1 和 2。该事件发生在两个组的 2017-01-022017-01-04 上。我正在尝试为这两个日期中的每一个创建一个列,并在该日期发生事件时填充该列。

我最初考虑使用case_when,然后使用以下pivot_wider

d %>% 
  mutate(event = case_when(
    dates == "2017-01-02" ~ 1,
    dates == "2017-01-04" ~ 1
  )) %>% 
  pivot_wider(names_from = dates, values_from = yes_no)

这不适用于我的数据,因为我遇到了内存问题,我不想为每个日期创建一个列,只为具有 event = 1 的日期创建一个列。或者,手动创建列然后直接填充日期可能很有用。

即 d$2017-01-02 = 0 ifelse(日期 = "2017-01-02", 2017-01-02 = 1, 0)

但是我有大约 30 个日期要填充并创建新列。

数据:

   d <- data.frame(
  dates = c("2017-01-01", "2017-01-02", "2017-01-03", "2017-01-04", "2017-01-05",
            "2017-01-01", "2017-01-02", "2017-01-03", "2017-01-04", "2017-01-05"),
  yes_no = c(0364, 2451, 32440, 234341, 123443,
             7273, 2331, 12332, 12233, 1232323),
  grp = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)
)

【问题讨论】:

    标签: r


    【解决方案1】:

    在base R中,我们可以使用lapply添加新列

    dates = c("2017-01-02", "2017-01-04")
    d[dates] <- lapply(dates, function(x) ifelse(d$dates == x, 1, NA))
    d
    
    #        dates  yes_no grp 2017-01-02 2017-01-04
    #1  2017-01-01     364   1         NA         NA
    #2  2017-01-02    2451   1          1         NA
    #3  2017-01-03   32440   1         NA         NA
    #4  2017-01-04  234341   1         NA          1
    #5  2017-01-05  123443   1         NA         NA
    #6  2017-01-01    7273   2         NA         NA
    #7  2017-01-02    2331   2          1         NA
    #8  2017-01-03   12332   2         NA         NA
    #9  2017-01-04   12233   2         NA          1
    #10 2017-01-05 1232323   2         NA         NA
    

    purrrlapply可以替换成map

    d[dates] <- purrr::map(dates, ~ifelse(d$dates == .x, 1, NA))
    

    【讨论】:

      【解决方案2】:

      为什么不明确创建日期列?

      d %>% 
        mutate(event = case_when(
          dates == "2017-01-02" ~ 1,
          dates == "2017-01-04" ~ 1
        ),
        `2017-01-02` = ifelse(dates == "2017-01-02", 1, NA),
        `2017-01-04` = ifelse(dates == "2017-01-04", 1, NA),
        )
      

      【讨论】:

        【解决方案3】:

        如果您的日期超过您提到的两个日期,这是一个(大部分)整洁的解决方案:

        library(dplyr)
        dates <- c("2017-01-02", "2017-01-04")
        d %>% 
          {
            l <- lapply(dates, function(x) ifelse(x == .$dates, 1, NA))
            names(l) <- dates
            cbind(., l)
          } %>% 
          mutate(event = select(., starts_with("201")) %>% rowSums(na.rm = TRUE))
        #>         dates  yes_no grp 2017-01-02 2017-01-04 event
        #> 1  2017-01-01     364   1         NA         NA     0
        #> 2  2017-01-02    2451   1          1         NA     1
        #> 3  2017-01-03   32440   1         NA         NA     0
        #> 4  2017-01-04  234341   1         NA          1     1
        #> 5  2017-01-05  123443   1         NA         NA     0
        #> 6  2017-01-01    7273   2         NA         NA     0
        #> 7  2017-01-02    2331   2          1         NA     1
        #> 8  2017-01-03   12332   2         NA         NA     0
        #> 9  2017-01-04   12233   2         NA          1     1
        #> 10 2017-01-05 1232323   2         NA         NA     0
        

        reprex package (v0.3.0) 于 2019 年 11 月 28 日创建

        如果您不喜欢它的外观,您可以将循环移动到一个函数中来完成同样的操作:

        add_date_column <- function(tbl, dates) {
            l <- lapply(dates, function(x) ifelse(x == tbl$dates, 1, NA))
            names(l) <- dates
            cbind(tbl, l)
        }
        d %>% 
          add_date_column(dates) %>% 
          mutate(event = select(., starts_with("201")) %>% rowSums(na.rm = TRUE))
        

        【讨论】:

          【解决方案4】:

          我们也可以在base R 中使用

          dates = c("2017-01-02", "2017-01-04")
          d[dates] <- NA^(sapply(dates, `!=`, d$dates))
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-01-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多