【问题标题】:Dataframe from a character vector where variable name and its data were stored jointly来自字符向量的数据帧,其中变量名称及其数据共同存储
【发布时间】:2022-01-26 01:51:03
【问题描述】:

我有这种情况:

foo <- data.frame("vars" = c("animal: mouse | wks: 12 | site: cage | PI: 78",
                            "animal: dog | wks: 32 | GI: 0.2",
                            "animal: cat | wks: 8 | site: wild | PI: 13"))

变量名称和相关数据存储在字符串中,如上例。特别是,每个 variable_name/its_data 单元由| 分隔。 :后面是相关数据。

我想要一个像这样的最终数据框:

  animal  wks  site  PI   GI
  mouse   12   cage  78   NA
    dog   32   <NA>  NA  0.2
    cat    8   wild  13   NA

【问题讨论】:

    标签: r dataframe strsplit


    【解决方案1】:

    我们可以使用来自base Rread.dcf

    out <- type.convert(as.data.frame(read.dcf(
        textConnection(paste(gsub("\\s+\\|\\s+", "\n", foo$vars), 
        collapse="\n\n")))), as.is = TRUE)
    

    -输出

    > out
      animal wks site PI  GI
    1  mouse  12 cage 78  NA
    2    dog  32 <NA> NA 0.2
    3    cat   8 wild 13  NA
    > str(out)
    'data.frame':   3 obs. of  5 variables:
     $ animal: chr  "mouse" "dog" "cat"
     $ wks   : int  12 32 8
     $ site  : chr  "cage" NA "wild"
     $ PI    : int  78 NA 13
     $ GI    : num  NA 0.2 NA
    

    【讨论】:

      【解决方案2】:

      这是dplyr 解决方案:

      library(dplyr)
      library(tidyr)
      
      tibble(foo) %>%
        mutate(row = row_number()) %>% 
        separate_rows(vars, sep = '\\|') %>% 
        separate(vars, c("a", "b"), sep = '\\:') %>% 
        mutate(across(everything(), str_trim)) %>% 
        group_by(a) %>% 
        pivot_wider(names_from = a, values_from = b) %>% 
        type.convert(as.is = TRUE) %>% 
        select(-row)
      
        animal   wks site     PI    GI
        <chr>  <int> <chr> <int> <dbl>
      1 mouse     12 cage     78  NA  
      2 dog       32 NA       NA   0.2
      3 cat        8 wild     13  NA 
      

      【讨论】:

        【解决方案3】:

        另一个使用 Reduce + merge 的基本 R 选项

        type.convert(
          Reduce(
            function(x, y) merge(x, y, all = TRUE),
            lapply(
              strsplit(foo$vars, ":|\\|"),
              function(x) {
                m <- matrix(trimws(x), 2)
                setNames(data.frame(m[2, , drop = FALSE]), m[1, ])
              }
            )
          ),
          as.is = TRUE
        )
        

        给予

          animal wks site PI  GI
        1    cat   8 wild 13  NA
        2    dog  32 <NA> NA 0.2
        3  mouse  12 cage 78  NA
        

        【讨论】:

          【解决方案4】:

          这是一种使用scan() 按行然后merge 的方法。

          lapply(1:nrow(foo), \(x) 
                 scan(text=foo[x, ], what=character(), sep='|', strip.white=T, qui=T) |>
            (\(.) do.call(rbind, strsplit(., ': ')))() |>
            (\(.) setNames(data.frame(t(.[, 2])), .[, 1]))()) |>
            (\(.) Reduce(\(...) merge(..., all=TRUE), .))()
          #   animal wks site   PI   GI
          # 1    cat   8 wild   13 <NA>
          # 2    dog  32 <NA> <NA>  0.2
          # 3  mouse  12 cage   78 <NA>
          

          注意: R >= 4.1 使用

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-10-23
            • 2022-11-11
            • 2013-06-04
            • 2020-12-20
            • 1970-01-01
            • 1970-01-01
            • 2013-07-13
            • 1970-01-01
            相关资源
            最近更新 更多