根据值将逗号分隔的数字列拆分为多个列

时间:2018-06-01 19:46:32

标签: r split dplyr tidyr strsplit

我的数据框中有一列df <- structure(list(f = c(NA, "18,17,10", "12,8", "17,11,6", "18", "12", "12", NA, "17,11", "12")), .Names = "f", row.names = c(NA, 10L), class = "data.frame") df # f # 1 <NA> # 2 18,17,10 # 3 12,8 # 4 17,11,6 # 5 18 # 6 12 # 7 12 # 8 <NA> # 9 17,11 # 10 12 ,我希望根据该列中的值将其分散到多个列中。例如:

f

如何将列 6 8 10 11 12 17 18 1 0 0 0 0 0 0 0 2 0 0 1 0 0 1 1 3 0 1 0 0 1 0 0 4 1 0 0 1 0 1 0 5 0 0 0 0 0 0 1 6 0 0 0 0 1 0 0 7 0 0 0 0 1 0 0 8 0 0 0 0 0 0 0 9 0 0 0 1 0 1 0 10 0 0 0 0 1 0 0 拆分为多个列,指示行中的数字。我对这样的事感兴趣:

unique

我想我可以在f列上使用grepl根据不同的数字创建单独的列,然后执行f以确定特定的数字是否在专栏spread,但我想知道是否有更好的方法。与separate包中的tidyrruby2.5-dev类似的内容。

2 个答案:

答案 0 :(得分:3)

这可以通过split ,stack到两列data.frame来获得,并获得频率table

df1 <- na.omit(stack(setNames(lapply(strsplit(df$f, ","), 
          as.numeric), seq_len(nrow(df))))[, 2:1])
table(df1)
#  values
#ind  6 8 10 11 12 17 18
#  1  0 0  0  0  0  0  0
#  2  0 0  1  0  0  1  1
#  3  0 1  0  0  1  0  0
#  4  1 0  0  1  0  1  0
#  5  0 0  0  0  0  0  1
#  6  0 0  0  0  1  0  0
#  7  0 0  0  0  1  0  0
#  8  0 0  0  0  0  0  0
#  9  0 0  0  1  0  1  0
#  10 0 0  0  0  1  0  0

答案 1 :(得分:2)

使用tidyr::separate_rows的解决方案如下:

library(tidyverse)
df %>% mutate(ind = row_number()) %>%
  separate_rows(f, sep=",") %>%
  mutate(f = ifelse(is.na(f),0, f)) %>%
  count(ind, f) %>%
  spread(f, n, fill = 0) %>%
  select(-2) %>% as.data.frame()

   # ind 10 11 12 17 18 6 8
# 1    1  0  0  0  0  0 0 0
# 2    2  1  0  0  1  1 0 0
# 3    3  0  0  1  0  0 0 1
# 4    4  0  1  0  1  0 1 0
# 5    5  0  0  0  0  1 0 0
# 6    6  0  0  1  0  0 0 0
# 7    7  0  0  1  0  0 0 0
# 8    8  0  0  0  0  0 0 0
# 9    9  0  1  0  1  0 0 0
# 10  10  0  0  1  0  0 0 0