将带有管道分隔数据的列转换为虚拟变量
Convert column with pipe delimited data into dummy variables
我有兴趣获取 data.frame 的一列,其中列中的值是竖线分隔的,并从竖线分隔的值创建虚拟变量。
例如:
假设我们从
开始
df = data.frame(a = c("Ben|Chris|Jim", "Ben|Greg|Jim|", "Jim|Steve|Ben"))
> df
a
1 Ben|Chris|Jim
2 Ben|Greg|Jim
3 Jim|Steve|Ben
我有兴趣结束:
df2 = data.frame(Ben = c(1, 1, 1), Chris = c(1, 0, 0), Jim = c(1, 1, 1), Greg = c(0, 1, 0),
Steve = c(0, 0, 1))
> df2
Ben Chris Jim Greg Steve
1 1 1 1 0 0
2 1 0 1 1 0
3 1 0 1 0 1
我事先不知道字段中有多少潜在值。在上面的示例中,变量 "a" 可以包含 1 个值或 10 个值。假设它是一个合理的数字(即 < 100 个可能的值)。
有什么好的方法吗?
这是一个使用 dplyr
和 tidyr
的选项:
library(dplyr)
library(tidyr)
df %>% tibble::rownames_to_column(var = "id") %>%
mutate(a = strsplit(as.character(a), "\|")) %>%
unnest() %>% table()
# a
# id Ben Chris Greg Jim Steve
# 1 1 1 0 1 0
# 2 1 0 1 1 0
# 3 1 0 0 1 1
碱基 R 中的类似物是:
df$a <- as.character(df$a)
s <- strsplit(df$a, "|", fixed=TRUE)
table(id = rep(1:nrow(df), lengths(s)), v = unlist(s))
数据:
df = data.frame(a = c("Ben|Chris|Jim", "Ben|Greg|Jim", "Jim|Steve|Ben"))
另一种方法是使用 splitstackshape
包中的 cSplit_e
。
按列 a
和 fill
0 和 drop
原始列拆分数据帧。
library(splitstackshape)
cSplit_e(df, "a", "|", type = "character", fill = 0, drop = T)
# a_Ben a_Chris a_Greg a_Jim a_Steve
#1 1 1 0 1 0
#2 1 0 1 1 0
#3 1 0 0 1 1
拆分 'a' 列后,我们可以使用 qdapTools
中的 mtabulate
library(qdapTools)
mtabulate(strsplit(as.character(df$a), "|", fixed = TRUE))
# Ben Chris Greg Jim Steve
#1 1 1 0 1 0
#2 1 0 1 1 0
#3 1 0 0 1 1
这是基本 R 中的一个方法
# get unique set of names
myNames <- unique(unlist(strsplit(as.character(df$a), split="\|")))
# get indicator data.frame
setNames(data.frame(lapply(myNames, function(i) as.integer(grepl(i, df$a)))), myNames)
哪个returns
Ben Chris Jim Greg Steve
1 1 1 1 0 0
2 1 0 1 1 0
3 1 0 1 0 1
第一行使用 strsplit
生成在管道“|”上拆分的名称列表,unlist
和 unique
生成唯一名称的向量。第二行用 lapply
遍历这些名称,并使用 grepl
搜索名称,as.integer
将其转换为二进制整数。返回的列表被转换为 data.frame 并使用 setNames
.
给出列名
我有兴趣获取 data.frame 的一列,其中列中的值是竖线分隔的,并从竖线分隔的值创建虚拟变量。
例如:
假设我们从
开始df = data.frame(a = c("Ben|Chris|Jim", "Ben|Greg|Jim|", "Jim|Steve|Ben"))
> df
a
1 Ben|Chris|Jim
2 Ben|Greg|Jim
3 Jim|Steve|Ben
我有兴趣结束:
df2 = data.frame(Ben = c(1, 1, 1), Chris = c(1, 0, 0), Jim = c(1, 1, 1), Greg = c(0, 1, 0),
Steve = c(0, 0, 1))
> df2
Ben Chris Jim Greg Steve
1 1 1 1 0 0
2 1 0 1 1 0
3 1 0 1 0 1
我事先不知道字段中有多少潜在值。在上面的示例中,变量 "a" 可以包含 1 个值或 10 个值。假设它是一个合理的数字(即 < 100 个可能的值)。
有什么好的方法吗?
这是一个使用 dplyr
和 tidyr
的选项:
library(dplyr)
library(tidyr)
df %>% tibble::rownames_to_column(var = "id") %>%
mutate(a = strsplit(as.character(a), "\|")) %>%
unnest() %>% table()
# a
# id Ben Chris Greg Jim Steve
# 1 1 1 0 1 0
# 2 1 0 1 1 0
# 3 1 0 0 1 1
碱基 R 中的类似物是:
df$a <- as.character(df$a)
s <- strsplit(df$a, "|", fixed=TRUE)
table(id = rep(1:nrow(df), lengths(s)), v = unlist(s))
数据:
df = data.frame(a = c("Ben|Chris|Jim", "Ben|Greg|Jim", "Jim|Steve|Ben"))
另一种方法是使用 splitstackshape
包中的 cSplit_e
。
按列 a
和 fill
0 和 drop
原始列拆分数据帧。
library(splitstackshape)
cSplit_e(df, "a", "|", type = "character", fill = 0, drop = T)
# a_Ben a_Chris a_Greg a_Jim a_Steve
#1 1 1 0 1 0
#2 1 0 1 1 0
#3 1 0 0 1 1
拆分 'a' 列后,我们可以使用 qdapTools
中的 mtabulate
library(qdapTools)
mtabulate(strsplit(as.character(df$a), "|", fixed = TRUE))
# Ben Chris Greg Jim Steve
#1 1 1 0 1 0
#2 1 0 1 1 0
#3 1 0 0 1 1
这是基本 R 中的一个方法
# get unique set of names
myNames <- unique(unlist(strsplit(as.character(df$a), split="\|")))
# get indicator data.frame
setNames(data.frame(lapply(myNames, function(i) as.integer(grepl(i, df$a)))), myNames)
哪个returns
Ben Chris Jim Greg Steve
1 1 1 1 0 0
2 1 0 1 1 0
3 1 0 1 0 1
第一行使用 strsplit
生成在管道“|”上拆分的名称列表,unlist
和 unique
生成唯一名称的向量。第二行用 lapply
遍历这些名称,并使用 grepl
搜索名称,as.integer
将其转换为二进制整数。返回的列表被转换为 data.frame 并使用 setNames
.