R拆分由不同数量的空格分隔的一列字符

Posted

技术标签:

【中文标题】R拆分由不同数量的空格分隔的一列字符【英文标题】:R splitting a column of character separated by different number of spaces 【发布时间】:2016-07-30 00:38:26 【问题描述】:

我有一个数据框,其中有一列由不同数量的空格分隔的单词组成,例如:

head(lst)
'fff fffd ddd'
'sss dd'
'de dd'
'dds sssd eew rrr'
'dsds eed'

我想要的是 2 列: 第一列是第一个空格之前的部分 第二列是最后一个空格之后的部分 意思应该是这样的

V1       v2
'fff'   'ddd'
'sss'   'dd'
'de'    'dd'
'dds'   'rrr
'dsds'  'eed'

我能得到第一列,但第二列有问题 这是我使用的代码。

  lst <- strsplit(athletes.df$V1, "\\s+")
  v1 <- sapply(lst ,`[`, 1)
  v2 <- sapply(lst, `[`, 2)

我得到的第 v2 列是第二个词。我知道这是因为我在 sapply 中放了 2 如何告诉它只取最后一个空格之后的内容?

【问题讨论】:

【参考方案1】:

您可以使用tail 来抓取每个向量的最后一个条目:

lst <- strsplit(athletes.df$V1, "\\s+")
v1 <- sapply(lst, head, 1) # example with head to grab first vector element
v2 <- sapply(lst, tail, 1) # example with tail to grab last vector element

或者可能是 vapply 版本,因为您知道返回类型应该是字符向量:

v2 <- vapply(lst, tail, 1, FUN.VALUE = character(1))

另一种方法是将您的 strsplit 拆分标准修改为类似这样的内容,您可以在一个空格上进行拆分,该空格可以选择后跟任何字符一次或多次,直到找到最终空格。

strsplit(df$V1, "\\s(?:.+\\s)?")
#[[1]]
#[1] "fff" "ddd"
#
#[[2]]
#[1] "sss" "dd" 
#
#[[3]]
#[1] "de" "dd"
#
#[[4]]
#[1] "dds" "rrr"
#
#[[5]]
#[1] "dsds" "eed"

正如 Sumedh 指出的,这个正则表达式可以很好地与 tidyrseparate 配合使用:

tidyr::separate(df, V1, c("V1", "V2"), "\\s(?:.+\\s)?")
#    V1  V2
#1  fff ddd
#2  sss  dd
#3   de  dd
#4  dds rrr
#5 dsds eed


两种基于stringi 的方法:

library(stringi)
v1 <- stri_extract_last_regex(df$V1, "\\S+")
v2 <- stri_extract_first_regex(df$V1, "\\S+")

或者

stri_extract_all_regex(df$V1, "^\\S+|\\S+$", simplify = TRUE)
# this variant explicitly checks for the spaces with lookarounds:
stri_extract_all_regex(df$V1, "^\\S+(?=\\s)|(?<=\\s)\\S+$", simplify = TRUE)

【讨论】:

正则表达式太棒了!或许你可以加tidyr::separate(df, V1, c("V1", "V2"), "\\s(?:.+\\s)?")【参考方案2】:

也许是这个?

lst <- strsplit(athletes.df$V1, "\\s+")
v1 <- sapply(lst ,`[`, 1)
v2 <- sapply(lst, function(x) x[length(x)])

或者

data.frame(t(sapply(strsplit(athletes.df$V1, "\\s+"), 
                    function(x) c(x[1], x[length(x)]))))

【讨论】:

【参考方案3】:

不使用任何包,这可以在使用sub 创建分隔符后使用read.table 完成。

read.table(text=sub("^(\\S+)\\s+.*\\s+(\\S+)$", "\\1 \\2", df1$V1), 
                     header=FALSE, stringsAsFactors= FALSE)
#     V1  V2
#1  fff ddd
#2  sss  dd
#3   de  dd
#4  dds rrr
#5 dsds eed

另一个方便的选项是word from stringr

library(stringr)
transform(df1, V1 = word(V1, 1), V2 = word(V1, -1))
#   V1  V2
#1  fff ddd
#2  sss  dd
#3   de  dd
#4  dds rrr
#5 dsds eed

数据

df1 <- structure(list(V1 = c("fff fffd ddd", "sss dd", "de dd",
"dds sssd eew rrr", 
"dsds eed")), .Names = "V1", class = "data.frame", row.names = c(NA, 
-5L))

【讨论】:

以上是关于R拆分由不同数量的空格分隔的一列字符的主要内容,如果未能解决你的问题,请参考以下文章

拆分由空白字符分隔的数字列。

将逗号分隔的字符串拆分为 R 中定义的数量

有没有一种简单的方法可以将由空格字符分隔的一行输入拆分为 C++ 中的整数?

用空格(或任何字符)将文本单元格拆分为任意数量的单词,重复单词

拆分空格分隔的字符串,忽略单引号内的空格

R语言之字符串的组合与拆分