【问题标题】:Dummify character column and find unique values [duplicate]虚拟化字符列并找到唯一值[重复]
【发布时间】:2023-02-21 22:19:58
【问题描述】:

我有一个具有以下结构的数据框

test <- data.frame(col = c('a; ff; cc; rr;', 'rr; a; cc; e;'))

现在我想从中创建一个数据框,其中包含测试数据框中每个唯一值的命名列。唯一值是以“;”结尾的值字符并以空格开头,不包括空格。然后对于列中的每一行,我希望用 1 或 0 填充虚拟列。如下所示

data.frame(a = c(1,1), ff = c(1,0), cc = c(1,1), rr = c(1,0), e = c(0,1))

  a ff cc rr e
1 1  1  1  1 0
2 1  0  1  1 1

我尝试使用 for 循环和列中的唯一值创建一个 df,但它变得很乱。我有一个可用的向量,其中包含列的唯一值。问题是如何创建 1 和 0。我用 grep() 尝试了一些 mutate_all() 函数,但这没有用。

【问题讨论】:

  • 你应该有 rr 两次 IIRC。

标签: r dummy-variable


【解决方案1】:

我会使用 splitstackshapeqdapTools 包中的 mtabulate 将其作为一个衬里, IE。

library(splitstackshape)
library(qdapTools)

mtabulate(as.data.frame(t(cSplit(test, 'col', sep = ';', 'wide'))))
#   a cc ff rr e
#V1 1  1  1  1 0
#V2 1  1  0  1 1

它也可以是完整的 splitstackshape,因为 @A5C1D2H2I1M1N2O1R2T1 在 cmets 中提到,

cSplit_e(test, "col", ";", mode = "binary", type = "character", fill = 0)

【讨论】:

  • 漂亮的班轮。
  • 实际的 1-liner 将是 cSplit_e(test, "col", ";", mode = "binary", type = "character", fill = 0) :-)
【解决方案2】:

这是一个可能的 data.table 实现。首先,我们将行拆分为列,合并为一列并将其展开,同时计算每一行的事件

library(data.table)
test2 <- setDT(test)[, tstrsplit(col, "; |;")]
dcast(melt(test2, measure = names(test2)), rowid(variable) ~ value, length)
#    variable a cc e ff rr
# 1:        1 1  1 0  1  1
# 2:        2 1  1 1  0  1

【讨论】:

    【解决方案3】:

    这是一个基本的 R 方法:

    x   <- strsplit(as.character(test$col), ";\s?") # split the strings
    lvl <- unique(unlist(x))                         # get unique elements
    x   <- lapply(x, factor, levels = lvl)           # convert to factor
    t(sapply(x, table))                              # count elements and transpose
    #     a ff cc rr e
    #[1,] 1  1  1  1 0
    #[2,] 1  0  1  1 1
    

    【讨论】:

      【解决方案4】:

      我们可以用tidyverse来做到这一点

      library(tidyverse)
      rownames_to_column(test, 'grp') %>%
              separate_rows(col) %>% 
              filter(col!="")  %>% 
              count( grp, col) %>%
              spread(col, n, fill = 0) %>%
              ungroup() %>% 
              select(-grp)
      # A tibble: 2 × 5
      #      a    cc     e    ff    rr
      #* <dbl> <dbl> <dbl> <dbl> <dbl>
      #1     1     1     0     1     1
      #2     1     1     1     0     1
      

      【讨论】:

        【解决方案5】:

        这是一个基本的 R 解决方案。先去掉空格。获得所有独特的组合。拆分实际数据框,然后检查它是否存在于将包含所有组合的 cols 中。然后你得到一个可以很容易地转换成数字的逻辑矩阵。

        test=as.data.frame(apply(test,2,function(x)gsub('\s+', '',x)))
        cols=unique(unlist(strsplit(as.character(test$col), split = ';'))) 
        yy=strsplit(as.character(test$col), split = ';') 
        z=as.data.frame(do.call.rbind(lapply(yy, function(x) cols %in% x)))
        names(z)=cols
        z=as.data.frame(lapply(z, as.integer))
        

        【讨论】:

          【解决方案6】:

          tidytexttidyverse 的另一种方法

          library(tidyverse)
          library(tidytext) #for unnest_tokens()
          df <- test %>%
              unnest_tokens(word, col) %>%
              rownames_to_column(var="row") %>%
              mutate(row = floor(parse_number(row)),
                     val = 1) %>%
              spread(word, val, fill = 0) %>%
              select(-row)
          df
          #    a cc e ff rr
          #1   1  1 0  1  1
          #2   1  1 1  0  1
          

          【讨论】:

            【解决方案7】:

            另一个没有任何额外包的简单解决方案:

            x =  c('a; ff; cc; rr;', 'rr; a; cc; e;')
            G = lapply(strsplit(x,';'), trimws)
            dict = sort(unique(unlist(G)))
            do.call(rbind, lapply(G, function(g) 1*sapply(dict, function(d) d %in% g)))
            

            【讨论】:

              猜你喜欢
              • 2017-07-12
              • 2011-01-09
              • 2013-07-18
              • 2017-04-10
              • 1970-01-01
              • 2013-05-09
              • 2018-07-15
              • 1970-01-01
              • 2014-06-27
              相关资源
              最近更新 更多