我的文本表看起来像这样:
in.data <- rbind(
c("ColA KB Col C The ColE (2.0)"),
c("abc def ghijklm n opqrst"),
c("uv wx y zzzzzz aa bcd"),
c("ab cd gh jklmn")
)
我需要这样:
wanted.result <- rbind(
c("abc", "def", "ghijklm", "n", "opqrst"),
c("uv", "wx y", "zzzzzz", "aa", "bcd"),
c("ab", "cd", NA, "gh", "jklmn")
)
colnames(wanted.result) <- c("ColA", "KB", "Col C", "The", "ColE (2.0)")
使复杂化的原因是垂直拆分分隔符位置可以基于列名和列内容。
这是一个有效的丑陋尝试:
library(stringr)
spaces.1 <- unique(unlist(str_locate_all(in.data[1,], " ")))
spaces.2 <- unique(unlist(str_locate_all(in.data[2,], " ")))
spaces.3 <- unique(unlist(str_locate_all(in.data[3,], " ")))
spaces.4 <- unique(unlist(str_locate_all(in.data[4,], " ")))
spaces.12 <- spaces.1[spaces.1%in%spaces.2]
spaces.123 <- spaces.12[spaces.12%in%spaces.3]
spaces.1234 <- spaces.123[spaces.123%in%spaces.4]
for (i in length(spaces.1234):2) {
if (spaces.1234[i]-spaces.1234[i-1]==1) spaces.1234[i] <- NA_integer_
}
delimiters <- na.omit(spaces.1234)
library(data.table)
in.data.table <- data.table(in.data)
in.data.table[, col.1:=substr(V1, start=1, stop=delimiters[1])]
in.data.table[, col.2:=substr(V1, start=delimiters[1], stop=delimiters[2])]
in.data.table[, col.3:=substr(V1, start=delimiters[2], stop=delimiters[3])]
in.data.table[, col.4:=substr(V1, start=delimiters[3], stop=delimiters[4])]
in.data.table[, col.5:=substr(V1, start=delimiters[4], stop=37)]
setnames(in.data.table, as.character(in.data.table[1, ]))
wanted.result.2 <- in.data.table[2:4, 2:6, with=FALSE]
但我需要这样做数千次,并且列数和行数不等。
有没有更好的方法来做到这一点,这也适用于任何数量的行?
更新:为了澄清,问题是根据标题和行中空格的位置找到宽度。很抱歉没有明白这一点。
答案 0 :(得分:2)
在使用read.fwf
调用找出定义列名称的内容后确定列宽后使用gregexpr
:
txt <- paste(c(in.data),collapse="\n")
widths <- diff(c(gregexpr("Col", in.data[1])[[1]], nchar(in.data[1])+1))
out <- read.fwf(textConnection(txt), widths=widths, skip=1)
names(out) <- unlist(read.fwf(textConnection(txt), widths=widths, n=1))
out
# ColA ColB Col C ColD ColE (2.0)
#1 abc def ghijklm n opqrst
#2 uv wx y zzzzzz aa bcd
#3 ab cd gh jklmn
答案 1 :(得分:2)
我们假设所有行中包含空格的列都会分隔字段,我们假设最后一个字段为10或更小(如果需要,请更改此数字)。没有包使用。
w <- diff(Reduce(intersect, gregexpr(" ", paste("", in.data))))
w <- c(w, 10)
X <- read.fwf(textConnection(in.data), w, skip = 1, as.is = TRUE)
names(X) <- trimws(read.fwf(textConnection(in.data), w, n = 1, as.is = TRUE))
X <- X[names(X) != "NA"]
X[] <- lapply(X, trimws)
,并提供:
> X
ColA ColB Col C ColD ColE (2.0)
1 abc def ghijklm n opqrst
2 uv wx y zzzzzz aa bcd
3 ab cd gh jklmn
注意:我们在上面的测试运行中使用它作为输入:
in.data <-
structure(c("ColA ColB Col C ColD ColE (2.0)", "abc def ghijklm n opqrst",
"uv wx y zzzzzz aa bcd", "ab cd gh jklmn"
), .Dim = c(4L, 1L))