在R中使用tidyr将字符串长度不均的行拆分为列

7

编辑:该问题被标记为重复。但事实并非如此。本题不仅涉及将单个列拆分为多个列,因为我的单独代码可以工作。我提出的主要问题是当行字符串具有不同长度的列输出时拆分列。

我试图将这个:

data <- c("Place1-Place2-Place2-Place4-Place2-Place3-Place5",
          "Place7-Place7-Place7-Place7-Place7-Place7-Place7-Place7",
          "Place1-Place1-Place1-Place1-Place3-Place5",
          "Place1-Place4-Place2-Place3-Place3-Place5-Place5",
          "Place6-Place6",
          "Place1-Place2-Place3-Place4")

转化为:

      X1     X2     X3     X4     X5     X6     X7     X8
1 Place1 Place2 Place2 Place4 Place2 Place3 Place5 
2 Place7 Place7 Place7 Place7 Place7 Place7 Place7 Place7
3 Place1 Place1 Place1 Place1 Place3 Place5 
4 Place1 Place4 Place2 Place3 Place3 Place5 Place5 
5 Place6 Place6 
6 Place1 Place2 Place3 Place4

我尝试使用tidyr的separate函数,代码如下:
library(data.table)
data <- as.data.table(data)
data_table <- tidyr::separate(data,
                            data,
                            sep="-",
                            into = strsplit(data$data, "-"),
                            fill = "right")

很遗憾,我遇到了这个错误:

Warning message:
Too many values at 3 locations: 1, 2, 4 

我需要做哪些改变才能使它工作?

你所说的不均匀字符串长度是什么意思?如果你想选择破折号之间的内容,可以尝试使用 [^-]+ 作为你的正则表达式。 - EDD
我认为这里的“uneven”应该是“未知”的意思 :) - Wiktor Stribiżew
@某人 是的,我指的是输出列。我尝试了你的建议,但警告变成了“警告信息:1个位置处有太多的值:2”。 - JnrfL
1个回答

9

您正确指定了目标列:

library(tidyr)
separate(DF, V1, paste0("X",1:8), sep="-")

这将会给出:

      X1     X2     X3     X4     X5     X6     X7     X8
1 Place1 Place2 Place2 Place4 Place2 Place3 Place5   <NA>
2 Place7 Place7 Place7 Place7 Place7 Place7 Place7 Place7
3 Place1 Place1 Place1 Place1 Place3 Place5   <NA>   <NA>
4 Place1 Place4 Place2 Place3 Place3 Place5 Place5   <NA>
5 Place6 Place6   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>
6 Place1 Place2 Place3 Place4   <NA>   <NA>   <NA>   <NA>

如果您事先不知道需要多少目标列,则可以使用以下方法:

如果您事先不知道需要多少目标列,则可以使用:

> max(sapply(strsplit(as.character(DF$V1),'-'),length))
[1] 8

提取最大数量的部分(因此是您需要的列数)。
其他几种方法: splitstackshape:
library(splitstackshape)
cSplit(DF, "V1", sep="-", direction = "wide")

stringi :

library(stringi)
as.data.frame(stri_list2matrix(stri_split_fixed(DF$V1, "-"), byrow = TRUE))

data.table :

library(data.table)
setDT(DF)[, paste0("v", 1:8) := tstrsplit(V1, "-")][, V1 := NULL][]

stringr :

library(stringr)
as.data.frame(str_split_fixed(DF$V1, "-",8))

所有这些都会得出类似的结果。


使用的数据:

DF <- data.frame(V1=c("Place1-Place2-Place2-Place4-Place2-Place3-Place5",
                      "Place7-Place7-Place7-Place7-Place7-Place7-Place7-Place7",
                      "Place1-Place1-Place1-Place1-Place3-Place5",
                      "Place1-Place4-Place2-Place3-Place3-Place5-Place5",
                      "Place6-Place6",
                      "Place1-Place2-Place3-Place4"))

谢谢回答!这个方法很好用,如果能用tidyr解决就更好了。 - JnrfL
@JnrfL 请查看更新后的答案,希望对你有帮助。 - Jaap

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接