【问题标题】:Transform a table - convert the column with semicolons separated values into multiple columns with Yes / No entries [duplicate]转换表 - 将用分号分隔的值的列转换为具有是/否条目的多列[重复]
【发布时间】:2015-01-27 09:09:58
【问题描述】:

我想将我当前的表格转换为可以轻松过滤的表格。

我有一个表,其中第一列是唯一标识符,第二列是与该条目相关的由分号分隔的问题列表。除此之外,我还有一些明确定义和布局的列。我的表可能看起来像这样:

|ID|Issue|Title|
|ABC.001.0001|Green; Blue|Around and up|
|ABC.001.0002|Green; Orange|Over and beyond|
|ABC.001.0003|Pink; Orange|Inside out|

每个 |上面表示表格中一列的结尾。

我想将表格转换为易于使用且易于过滤的问题。这将是一个很好的结果:

|ID|Green|Blue|Orange|Pink|Title|
|ABC.001.0001|Yes|Yes|No|No|Around and up|
|ABC.001.0002|Yes|No|Yes|No|Over and beyond|
|ABC.001.0003|No|No|Yes|Yes|Inside out|

我不想写很多代码。我想找到一些可以在 R 或 Octave 等几个步骤中完成这种转换的库。否则,也许我可以在 MS Excel 和 MS Access 中采取一些步骤来获得相同的结果。

作为一个附带问题,这种转换称为什么?数据整齐?正常化?蒙宁?

【问题讨论】:

    标签: r excel normalization


    【解决方案1】:

    您可以使用 splitstackshape 中的 cSplit 将“问题”列用分号 (sep=';') 分隔。指定long 的方向,然后使用dcast.data.table 将其重新整形为wide。然后根据它是否具有NA,将“蓝色”到“粉红色”列中的“值”更改为“是/否”。但是,与Yes/No 相比,将结果作为逻辑索引TRUE/FALSE 总是更好(我们将从!is.na 步骤获得)。

    library(splitstackshape)
    library(data.table)
    res <- dcast.data.table(cSplit(df, 'Issue', sep=';', 'long'),
                       ID+Title~Issue, value.var='Issue')
    
    nm1 <- names(res)[3:6]
     res[,(nm1):=lapply(.SD, function(x) 
              c("No", "Yes")[(!is.na(x))+1L]), .SDcols=nm1]
    
     res
     #             ID           Title Blue Green Orange Pink
     #1: ABC.001.0001   Around and up  Yes   Yes     No   No
     #2: ABC.001.0002 Over and beyond   No   Yes    Yes   No
     #3: ABC.001.0003      Inside out   No    No    Yes  Yes
    

    或者您可以使用cSplit_e(来自@Ananda Mahto 的 cmets)

     cSplit_e(df, "Issue", sep = "; ", type = "character",
                     fill = 0, drop = TRUE)
    

    或使用base R 的选项。在这里,我使用strsplit 拆分“问题”列,然后使用rbind 列表输出创建“m1”。创建一个唯一值向量(“lvls”)。使用 apply 和 MARGIN 为“1”检查哪些“lvls”在“m1”(lvls %in% x)的每一行中。通过向其添加“1”('x)+1L`)将逻辑向量转换为数字,并将其用作“是/否”值的索引。

     df1 <-  df[-2]
     m1 <- do.call(rbind,strsplit(df$Issue, '; '))
     lvls <- unique(c(m1))
     df1[lvls] <-  t(apply(m1, 1, function(x) c('No', 'Yes')[(lvls
                                    %in% x)+1L]))
     df1
     #            ID           Title Green Pink Blue Orange
     #1 ABC.001.0001   Around and up   Yes   No  Yes     No
     #2 ABC.001.0002 Over and beyond   Yes   No   No    Yes
     #3 ABC.001.0003      Inside out    No  Yes   No    Yes
    

    数据

     df <- structure(list(ID = c("ABC.001.0001", "ABC.001.0002", 
     "ABC.001.0003"), Issue = c("Green; Blue", "Green; Orange", "Pink; Orange"), 
    Title = c("Around and up", "Over and beyond", "Inside out")), 
    .Names = c("ID", "Issue", "Title"), class = "data.frame", 
    row.names = c(NA, -3L))
    

    【讨论】:

    • 我会在这里给你投票,但我认为你不应该鼓励 OP 在逻辑 TRUE/FALSE 选项存在时使用“是/否”值。我个人会建议cSplit_e(df, "Issue", sep = "; ", type = "character", fill = 0, drop = TRUE)
    • 非常感谢阿克伦和阿南达。这正是我想要的。
    猜你喜欢
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 2012-12-02
    • 2014-08-24
    • 2020-09-29
    • 1970-01-01
    相关资源
    最近更新 更多