将逗号分隔的列条目拆分为行

Posted

技术标签:

【中文标题】将逗号分隔的列条目拆分为行【英文标题】:split comma-separated column entry into rows 【发布时间】:2015-02-02 19:22:50 【问题描述】:

我已经找到了同一问题的其他版本,但我无法针对我的问题调整那里给出的答案。这是older link:

那里的操作只包含两列的数据 - 给定的答案很好地处理了这个问题。但是超过两列呢?有没有办法适配链接代码sn-p?

这是一个例子:

ve <- rbind("4,2","3","1,2,3","5","6","7")
expl <- cbind(head(mtcars),ve)

    row.names           mpg     cyl     disp    hp      drat    wt      qsec    vs  am  gear carb   ve
1   Mazda RX4           21.0    6       160     110     3.90    2.620   16.46   0   1   4    4      4,2
2   Mazda RX4 Wag       21.0    6       160     110     3.90    2.875   17.02   0   1   4    4      3
3   Datsun 710          22.8    4       108     93      3.85    2.320   18.61   1   1   4    1      1,2,3
4   Hornet 4 Drive      21.4    6       258     110     3.08    3.215   19.44   1   0   3    1      5
5   Hornet Sportabout   18.7    8       360     175     3.15    3.440   17.02   0   0   3    2      6
6   Valiant             18.1    6       225     105     2.76    3.460   20.22   1   0   3    1      7

我需要:

    row.names           mpg     cyl     disp    hp      drat    wt      qsec    vs  am  gear carb   ve
1   Mazda RX4           21.0    6       160     110     3.90    2.620   16.46   0   1   4    4      4
2   Mazda RX4           21.0    6       160     110     3.90    2.620   16.46   0   1   4    4      2
3   Mazda RX4 Wag       21.0    6       160     110     3.90    2.875   17.02   0   1   4    4      3
4   Datsun 710          22.8    4       108     93      3.85    2.320   18.61   1   1   4    1      1
5   Datsun 710          22.8    4       108     93      3.85    2.320   18.61   1   1   4    1      2
6   Datsun 710          22.8    4       108     93      3.85    2.320   18.61   1   1   4    1      3
7   Hornet 4 Drive      21.4    6       258     110     3.08    3.215   19.44   1   0   3    1      5
8   Hornet Sportabout   18.7    8       360     175     3.15    3.440   17.02   0   0   3    2      6
9   Valiant             18.1    6       225     105     2.76    3.460   20.22   1   0   3    1      7

谢谢!

【问题讨论】:

所以你想插入重复的行?以后可能会变得一团糟。 【参考方案1】:

尝试tidyr 包中的unnest。我的示例使用dplyr,但您也可以使用基本函数来完成。

library(dplyr)
library(tidyr)

expl %>%
  mutate(ve = strsplit(as.character(ve), ",")) %>% 
  unnest(ve)

【讨论】:

【参考方案2】:

这是一个仅使用基数 R 的尝试(它还保留了行名 - 至少在某种程度上......)

ve <- strsplit(ve, ",")
Res <- expl[rep(seq_len(nrow(expl)), sapply(ve, length)), ]
Res$ve <- unlist(ve)
Res
#                    mpg cyl disp  hp drat    wt  qsec vs am gear carb ve
# Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4  4
# Mazda RX4.1       21.0   6  160 110 3.90 2.620 16.46  0  1    4    4  2
# Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4  3
# Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  1
# Datsun 710.1      22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  2
# Datsun 710.2      22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  3
# Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1  5
# Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2  6
# Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1  7

或者使用data.table,一种选择是

library(data.table)
setDT(expl)[, 
            strsplit(as.character(ve), ","), 
            c(names(expl)[-length(expl)])
            ]

另一种选择是

setkey(expl, ve)[setDT(expl)[, strsplit(as.character(ve), ","), ve]]

【讨论】:

我已经在当前项目中使用了来自 data.table 的 fread,所以我将使用它 - 非常好!【参考方案3】:

我会从我的“splitstackshape”包中推荐cSplit

由于您的示例具有 rownames,因此我已使用 keep.rownames = TRUE 参数将您的示例数据转换为 data.table

library(splitstackshape)
cSplit(as.data.table(expl, keep.rownames = TRUE), "ve", ",", "long")
#                   rn  mpg cyl disp  hp drat    wt  qsec vs am gear carb ve
# 1:         Mazda RX4 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4  4
# 2:         Mazda RX4 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4  2
# 3:     Mazda RX4 Wag 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4  3
# 4:        Datsun 710 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  1
# 5:        Datsun 710 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  2
# 6:        Datsun 710 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  3
# 7:    Hornet 4 Drive 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1  5
# 8: Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2  6
# 9:           Valiant 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1  7

【讨论】:

以上是关于将逗号分隔的列条目拆分为行的主要内容,如果未能解决你的问题,请参考以下文章

在Oracle中将连字符分隔的字符串拆分为行

将逗号分隔的条目拆分为新行(无 VBA)

将逗号分隔值拆分为 Oracle 中的列

拆分包含逗号分隔条目的字符串流

拆分逗号分隔的字符串,同时删除空格和空条目

将逗号分隔的单元格拆分为多行,保持原始行不变?