将包含列表的列变成虚拟对象
Turn colum containing list into dummies
我有一个数据框,其中包含(space 分隔的)年份列表,我想将其变成每年的虚拟变量。
考虑以下玩具数据:
raw <- data.frame(textcol = c("case1", "case2", "case3"), years=c('1996 1997 1998','1997 1999 2000', '1996 1998 2000'))
textcol years
1 case1 1996 1997 1998
2 case2 1997 1999 2000
3 case3 1996 1998 2000
我现在想将数据框转换成这个
textcol `1996` `1997` `1998` `1999` `2000`
1 case1 1 1 1 0 0
2 case2 0 1 0 1 1
3 case3 1 0 1 0 1
我尝试使用 separate()
和 str_split()
无济于事。有人能告诉我正确的方法吗?
您可以使用 strsplit
拆分成单独的年份,rep
textcol 并使用 table
.
. <- strsplit(raw$years, " ", TRUE)
table(rep(raw$textcol, lengths(.)), unlist(.))
# 1996 1997 1998 1999 2000
# case1 1 1 1 0 0
# case2 0 1 0 1 1
# case3 1 0 1 0 1
或使用 stack
的管道版本。
strsplit(raw$years, " ", TRUE) |>
setNames(raw$textcol) |>
stack() |>
rev() |>
table()
# values
#ind 1996 1997 1998 1999 2000
# case1 1 1 1 0 0
# case2 0 1 0 1 1
# case3 1 0 1 0 1
使用 separate_rows
将每一年放在单独的行中,然后使用 table
。 (如果您希望将其作为数据框,请将 %>% as.data.frame.matrix
附加到管道。)
library(tidyr)
tab <- raw %>% separate_rows(years) %>% table
给予:
tab
## years
## textcol 1996 1997 1998 1999 2000
## case1 1 1 1 0 0
## case2 0 1 0 1 1
## case3 1 0 1 0 1
我们可以将其显示为图表。将 tab 转换为 igraph,g。然后创建一个自定义布局 lay,按顺序显示顶点,因为 igraph 中通常的二分布局会尝试对它们重新排序以最小化交叉点。终于画出来了
library(igraph)
g <- graph_from_incidence_matrix(tab)
lay <- with(as.data.frame(layout_as_bipartite(g)),
cbind(ave(V1, V2, FUN = sort), V2))
plot(g, layout = lay, vertex.size = 2)
将 separate_rows
与 pivot_wider
一起使用:
library(tidyverse)
raw %>%
separate_rows(years) %>%
mutate(value = 1) %>%
pivot_wider(textcol, names_from = years, values_from = value, values_fill = 0)
# A tibble: 3 x 6
textcol `1996` `1997` `1998` `1999` `2000`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 case1 1 1 1 0 0
2 case2 0 1 0 1 1
3 case3 1 0 1 0 1
另一个解决方案 fastDummies::dummyCols
和有用的 split
参数。
fastDummies::dummy_cols(raw, "years", split = " ", remove_selected_columns = T)
textcol years_1996 years_1997 years_1998 years_2000 years_1999
1 case1 1 1 1 0 0
2 case2 0 1 0 1 1
3 case3 1 0 1 1 0
一个data.table
选项
> library(data.table)
> dcast(setDT(raw)[, strsplit(years, " "), textcol], textcol ~ V1, fun = length)
textcol 1996 1997 1998 1999 2000
1: case1 1 1 1 0 0
2: case2 0 1 0 1 1
3: case3 1 0 1 0 1
我有一个数据框,其中包含(space 分隔的)年份列表,我想将其变成每年的虚拟变量。
考虑以下玩具数据:
raw <- data.frame(textcol = c("case1", "case2", "case3"), years=c('1996 1997 1998','1997 1999 2000', '1996 1998 2000'))
textcol years
1 case1 1996 1997 1998
2 case2 1997 1999 2000
3 case3 1996 1998 2000
我现在想将数据框转换成这个
textcol `1996` `1997` `1998` `1999` `2000`
1 case1 1 1 1 0 0
2 case2 0 1 0 1 1
3 case3 1 0 1 0 1
我尝试使用 separate()
和 str_split()
无济于事。有人能告诉我正确的方法吗?
您可以使用 strsplit
拆分成单独的年份,rep
textcol 并使用 table
.
. <- strsplit(raw$years, " ", TRUE)
table(rep(raw$textcol, lengths(.)), unlist(.))
# 1996 1997 1998 1999 2000
# case1 1 1 1 0 0
# case2 0 1 0 1 1
# case3 1 0 1 0 1
或使用 stack
的管道版本。
strsplit(raw$years, " ", TRUE) |>
setNames(raw$textcol) |>
stack() |>
rev() |>
table()
# values
#ind 1996 1997 1998 1999 2000
# case1 1 1 1 0 0
# case2 0 1 0 1 1
# case3 1 0 1 0 1
使用 separate_rows
将每一年放在单独的行中,然后使用 table
。 (如果您希望将其作为数据框,请将 %>% as.data.frame.matrix
附加到管道。)
library(tidyr)
tab <- raw %>% separate_rows(years) %>% table
给予:
tab
## years
## textcol 1996 1997 1998 1999 2000
## case1 1 1 1 0 0
## case2 0 1 0 1 1
## case3 1 0 1 0 1
我们可以将其显示为图表。将 tab 转换为 igraph,g。然后创建一个自定义布局 lay,按顺序显示顶点,因为 igraph 中通常的二分布局会尝试对它们重新排序以最小化交叉点。终于画出来了
library(igraph)
g <- graph_from_incidence_matrix(tab)
lay <- with(as.data.frame(layout_as_bipartite(g)),
cbind(ave(V1, V2, FUN = sort), V2))
plot(g, layout = lay, vertex.size = 2)
将 separate_rows
与 pivot_wider
一起使用:
library(tidyverse)
raw %>%
separate_rows(years) %>%
mutate(value = 1) %>%
pivot_wider(textcol, names_from = years, values_from = value, values_fill = 0)
# A tibble: 3 x 6
textcol `1996` `1997` `1998` `1999` `2000`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 case1 1 1 1 0 0
2 case2 0 1 0 1 1
3 case3 1 0 1 0 1
另一个解决方案 fastDummies::dummyCols
和有用的 split
参数。
fastDummies::dummy_cols(raw, "years", split = " ", remove_selected_columns = T)
textcol years_1996 years_1997 years_1998 years_2000 years_1999
1 case1 1 1 1 0 0
2 case2 0 1 0 1 1
3 case3 1 0 1 1 0
一个data.table
选项
> library(data.table)
> dcast(setDT(raw)[, strsplit(years, " "), textcol], textcol ~ V1, fun = length)
textcol 1996 1997 1998 1999 2000
1: case1 1 1 1 0 0
2: case2 0 1 0 1 1
3: case3 1 0 1 0 1