转换 table - 将分号分隔值的列转换为具有是/否条目的多列
Transform a table - convert the column with semicolons separated values into multiple columns with Yes / No entries
我想将我目前的 table 转换成可以轻松过滤的。
我有一个 table,其中第一列是唯一标识符,第二列是与该条目相关的由分号分隔的问题列表。除此之外,我还有一些明确定义和布局的专栏。我的 table 可能看起来像这样:
|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|
每个 |上面表示table.
中一列的结尾
我想将 table 转换为易于使用和易于筛选的问题。这将是一个很好的结果:
|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 中采取一些步骤来获得相同的结果。
附带一个问题,这个转换叫什么?整理数据?正常化?芒格?
您可以使用 splitstackshape
中的 cSplit
通过分号 (sep=';'
) 拆分 "Issue" 列。指定 long
的方向,然后使用 dcast.data.table
将其整形回 wide
。然后根据是否有NA,将"Blue"到"Pink"列中的"values"改为"Yes/No"。但是,与 Yes/No
(我们将从 !is.na
步骤中获得)相比,将结果作为逻辑索引 TRUE/FALSE
总是更好。
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 的评论)
cSplit_e(df, "Issue", sep = "; ", type = "character",
fill = 0, drop = TRUE)
或使用 base R
的选项。在这里,我使用 strsplit
拆分 "Issue" 列,然后 rbind
列表输出以创建 "m1"。创建唯一值向量 ("lvls")。使用 apply
和 MARGIN 为“1”检查 "m1"(lvls %in% x
)的每一行中有哪些 "lvls"。通过向其添加“1”('x)+1L`) 将逻辑向量转换为数值,并将其用作 "Yes/No" 值的索引。
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))
我想将我目前的 table 转换成可以轻松过滤的。
我有一个 table,其中第一列是唯一标识符,第二列是与该条目相关的由分号分隔的问题列表。除此之外,我还有一些明确定义和布局的专栏。我的 table 可能看起来像这样:
|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|
每个 |上面表示table.
中一列的结尾我想将 table 转换为易于使用和易于筛选的问题。这将是一个很好的结果:
|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 中采取一些步骤来获得相同的结果。
附带一个问题,这个转换叫什么?整理数据?正常化?芒格?
您可以使用 splitstackshape
中的 cSplit
通过分号 (sep=';'
) 拆分 "Issue" 列。指定 long
的方向,然后使用 dcast.data.table
将其整形回 wide
。然后根据是否有NA,将"Blue"到"Pink"列中的"values"改为"Yes/No"。但是,与 Yes/No
(我们将从 !is.na
步骤中获得)相比,将结果作为逻辑索引 TRUE/FALSE
总是更好。
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 的评论)
cSplit_e(df, "Issue", sep = "; ", type = "character",
fill = 0, drop = TRUE)
或使用 base R
的选项。在这里,我使用 strsplit
拆分 "Issue" 列,然后 rbind
列表输出以创建 "m1"。创建唯一值向量 ("lvls")。使用 apply
和 MARGIN 为“1”检查 "m1"(lvls %in% x
)的每一行中有哪些 "lvls"。通过向其添加“1”('x)+1L`) 将逻辑向量转换为数值,并将其用作 "Yes/No" 值的索引。
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))