【问题标题】:Split dataframe columns according to string pattern matching根据字符串模式匹配拆分数据框列
【发布时间】:2021-04-17 21:38:35
【问题描述】:

问题 - 数据整理:

我想微调多项选择题考试的注释,每个问题有 5 个项目 - A、B、C、D、E。我想在每个可能的项目上使用系数。为此,我需要做一些数据整理:

输入:

library(tibble)

(
  df <- tribble(
  ~id,   ~Q1,   ~Q2,   ~Q3, 
#|----|------|------|------|
    1,  "CDE",   "A",  "AD",
    2,  "CDE",  "AB",  "AD",
    3,   "DE",  "BC",  "AD")
)

预期输出:

id Q1_A Q1_B Q1_C Q1_D Q1_E Q2_A Q2_B Q2_C Q2_D Q2_E Q3_A Q3_B Q3_C Q3_D Q3_E
1 0 0 1 1 1 1 0 0 0 0 1 0 0 1 0
2 0 0 1 1 1 1 1 0 0 0 1 0 0 1 0
3 0 0 0 1 1 0 1 1 0 0 1 0 0 1 0

【问题讨论】:

    标签: r dataframe split


    【解决方案1】:

    我们可以通过拆分使用mtabulate

    library(qdapTools)
    cbind(df[1], do.call(cbind, lapply(df[-1],
           function(x) mtabulate(strsplit(x, "")))))
    

    或者使用base Rtable 在使用strsplit 拆分每个列值后,获取频率计数,然后获取cbind list 元素

    cbind(df[1], do.call(cbind, lapply(df[-1], function(x) {
           x1 <- strsplit(x, "")
     as.data.frame.matrix(table(data.frame(ind = rep(seq_along(x1), 
        lengths(x1)), val = factor(unlist(x1), levels = LETTERS[1:5]))))})))
    

    -输出

    #  id Q1.A Q1.B Q1.C Q1.D Q1.E Q2.A Q2.B Q2.C Q2.D Q2.E Q3.A Q3.B Q3.C Q3.D Q3.E
    #1  1    0    0    1    1    1    1    0    0    0    0    1    0    0    1    0
    #2  2    0    0    1    1    1    1    1    0    0    0    1    0    0    1    0
    #3  3    0    0    0    1    1    0    1    1    0    0    1    0    0    1    0
    

    【讨论】:

      【解决方案2】:

      另一个基本 R 选项

      cbind(
        df[1],
        `colnames<-`(
          do.call(
            cbind,
            lapply(
              df[-1],
              function(x) {
                t(sapply(
                  strsplit(x, ""),
                  function(v) table(factor(v, levels = LETTERS[1:5]))
                ))
              }
            )
          ),
          paste0(rep(names(df)[-1], each = 5), "_", LETTERS[1:5])
        )
      )
      

      给了

        id Q1_A Q1_B Q1_C Q1_D Q1_E Q2_A Q2_B Q2_C Q2_D Q2_E Q3_A Q3_B Q3_C Q3_D Q3_E
      1  1    0    0    1    1    1    1    0    0    0    0    1    0    0    1    0
      2  2    0    0    1    1    1    1    1    0    0    0    1    0    0    1    0
      3  3    0    0    0    1    1    0    1    1    0    0    1    0    0    1    0
      

      【讨论】:

        【解决方案3】:

        来自其他海报的非常聪明的单行字,但很难破译。

        恕我直言,这是一个更具可读性的解决方案:

        ABCDE <- LETTERS[1:5]
        one_col_to_five <- function(col) sapply(ABCDE,  grepl, col)
        (proper_df <- do.call(cbind, lapply(df[, -1], one_col_to_five)))
        (proper_df <- as.data.frame(cbind(df$id, proper_df)))
        
        names(proper_df) <- c("id", paste(rep(names(df[-1]), 5), ABCDE, sep = "_"))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-08
          相关资源
          最近更新 更多