按多个空格分割字符串

5
我正在尝试将以下格式(作为文本文件)的数据加载到R中:
Name                  Country            Age
John,Smith            United Kingdom     20
Washington,George     USA                50
Martin,Joseph         Argentina          43

我遇到的问题是,“列”之间用空格分隔,以便它们都能很好地对齐,但是一行可能在值之间有5个空格,而下一行则有10个空格。因此,当我使用read.delim加载时,我会得到一个只有一列的数据框。
"John,Smith            United Kingdom     20"

作为第一次观察等等。
我能否采取以下任一方式:
1. 将数据加载到R中并转换为可用格式? 2. 一旦我将其加载到一个列格式中,就将字符字符串拆分成单独的列?
我的想法是通过空格拆分字符字符串,但需要在2到x个空格之间(因此,“United Kingdom”保持不变,不会变成“United”“”“Kingdom”)。但我不知道这是否可能。
我尝试了strsplit(data.frame[,1], sep="\\s")但它返回一组像这样的字符字符串:
"John,Smith" "" "" "" "" "" "" "" "United" "" "Kingdom" "" ""...

“我不知道如何处理它。”

4
看起来你有固定宽度的数据。考虑使用read.fwf(或"readr"包中的read_fwf)代替。 - A5C1D2H2I1M1N2O1R2T1
1
参数应该拆分而不是sep,并且应该是 '\\s{2,}',例如 rl <- readLines('~/desktop/txt'); do.call('rbind', strsplit(rl, '\\s{2,}')),但是read.fwf是正确的方式。 - rawr
有没有人见过一个读取函数,它需要超过一个单一字符的 sep(或者至少是一个量词)?还是我只能使用 strsplit - alistaire
1
@alistaire,从"gsubfn"中使用read.pattern - A5C1D2H2I1M1N2O1R2T1
2个回答

4
拥有所有“完美对齐”的列是固定宽度数据的典型特征。为了回答这个问题,我已经将您的三行数据和一行标题信息写入一个名为“x”的临时文件中。对于您实际使用的情况,请用文件名/路径替换“x”,就像您通常使用read.delim一样。以下是示例数据:
x <- tempfile()
cat("Name                  Country            Age\nJohn,Smith            United Kingdom     20\nWashington,George     USA                50\nMartin,Joseph         Argentina          43\n", file = x)

R有自己的读取定宽数据的函数(read.fwf),但是它非常慢,而且在开始之前需要知道宽度。如果文件很小,我们可以计算宽度,然后使用以下内容:

read.fwf(x, c(22, 18, 4), strip.white = TRUE, skip = 1, 
         col.names = c("Name", "Country", "Age"))
#                Name        Country Age
# 1        John,Smith United Kingdom  20
# 2 Washington,George            USA  50
# 3     Martin,Joseph      Argentina  43

或者,您可以让“readr”软件包中的fwf_widths为您猜测宽度,然后使用read_fwf

library(readr)
read_fwf(x, fwf_empty(x, col_names = c("Name", "Country", "Age")), skip = 1)
#                Name        Country Age
# 1        John,Smith United Kingdom  20
# 2 Washington,George            USA  50
# 3     Martin,Joseph      Argentina  43

2

如果您的列中不包含超过1个空格的单词,您可以使用基本的R操作:

txt = "Name                  Country            Age
John,Smith            United Kingdom     20
Washington,George     USA                50
Martin,Joseph         Argentina          43"

conn = textConnection(txt)
do.call(rbind, lapply(readLines(conn), function(u) strsplit(u,'\\s{2,}')[[1]]))
#     [,1]                [,2]             [,3] 
#[1,] "Name"              "Country"        "Age"
#[2,] "John,Smith"        "United Kingdom" "20" 
#[3,] "Washington,George" "USA"            "50" 
#[4,] "Martin,Joseph"     "Argentina"      "43" 

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