【问题标题】:Using tidyverse and pipes how do I assign fixed rows使用 tidyverse 和管道如何分配固定行
【发布时间】:2020-03-14 18:43:13
【问题描述】:

给定这个数据框

X1          X2   
2001        NA
abc         10
def         12
xo          13
2002        NA
abc         10
efd         22
dd          23
2005        NA
a           30

所有年份在 X2 中都有 NA。我的目标是让这个数据框成为

X1          X2        Date
abc         10        2001
def         12        2001
xo          13        2001
abc         10        2002
efd         22        2002
dd          23        2002
a           30        2005

也就是说,年份变成了自己的专栏,而 NA 被删除了

我尝试了什么

a = read_csv("given.csv")
a %>% mutate(Date = ifelse(is.na(X2), X1, NA)) 

这会将第一个数据帧变为

X1          X2      Date
2001        NA      2001
abc         10      NA
def         12      NA
xo          13      NA
2002        NA      2002
abc         10      NA
efd         22      NA
dd          23      NA
2005        NA      2005
a           30      NA

我不确定如何将日期列的 NA 替换为每年的上限值。在那之后,我想我可以直接 drop_na,就像我想要它一样

【问题讨论】:

    标签: r tidyverse


    【解决方案1】:

    另一种选择:

    library(dplyr)
    library(zoo)
    
    a %>% 
      mutate(Date = na.locf(case_when(is.na(X2) ~ X1))) %>%
      na.omit
    

    输出:

        X1 X2 Date
    2  abc 10 2001
    3  def 12 2001
    4   xo 13 2001
    6  abc 10 2002
    7  efd 22 2002
    8   dd 23 2002
    10   a 30 2005
    

    如果您想重置行号,只需使用 filter(!is.na(X2)) 而不是 na.omit

    附:您当然可以只加载 tidyverse 并执行以下操作:

    library(tidyverse)
    
    a %>% 
      mutate(Date = case_when(is.na(X2) ~ X1)) %>%
      fill(Date) %>%
      drop_na
    

    .. 但是请注意,与 zoo 中的 na.locf 函数相比,fill 相当慢。

    【讨论】:

      【解决方案2】:

      我们可以根据'X1'中仅数字元素(\\d+)的出现创建一个分组列,得到累积和,创建'Date'作为'X1'的first元素,@987654323 @ 并删除 NA 行

      library(dplyr)
      library(stringr)
      a %>%
          group_by(grp = cumsum(str_detect(X1, '^\\d+$'))) %>% 
          mutate(Date = first(X1)) %>%
          ungroup %>% 
          select(-grp) %>%
          na.omit
      # A tibble: 7 x 3
      #  X1       X2 Date 
      #  <chr> <int> <chr>
      #1 abc      10 2001 
      #2 def      12 2001 
      #3 xo       13 2001 
      #4 abc      10 2002 
      #5 efd      22 2002 
      #6 dd       23 2002 
      #7 a        30 2005 
      

      或者使用data.tablezoo

      library(data.table)
      library(zoo)
      na.omit(setDT(a)[, Date := na.locf(fifelse(is.na(X2), X1, NA_character_))])
      

      数据

      a <- structure(list(X1 = c("2001", "abc", "def", "xo", "2002", "abc", 
      "efd", "dd", "2005", "a"), X2 = c(NA, 10L, 12L, 13L, NA, 10L, 
      22L, 23L, NA, 30L)), class = "data.frame", row.names = c(NA, 
      -10L))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-08-10
        • 2018-11-15
        • 2019-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-11
        相关资源
        最近更新 更多