我希望能够从数据框中的字符向量中提取特定字符并返回新的数据框。我想提取的信息是审计员对特定公司收入和资产负债表的评论。我的问题是审核员备注存储在包含不同备注的向量中。例如:
vec = c("A C G H D E")
。由于"A" %in% vec
不会返回TRUE
,因此我必须使用strsplit
来分解数据框中的每个字符向量,因此"A" %in% unlist(strsplit(dat[i, 2], " ")
。这将返回TRUE
。
这是一个MWE:
dat <- data.frame(orgnr = c(1, 2, 3, 4), rat = as.character(c("A B C")))
dat$rat <- as.character(dat$rat)
dat[2, 2] <- as.character(c("A F H L H"))
dat[3, 2] <- as.character(c("H X L O"))
dat[4, 2] <- as.character(c("X Y Z A B C"))
现在,为了提取有关rat
coloumn中每个字母的信息,我尝试了几种方法,遵循类似的问题,例如Roland对类似问题的回答(How to split a character vector into data frame?)
DF <- data.frame(do.call(rbind, strsplit(dat$rat, " ", fixed = TRUE)))
DF
X1 X2 X3 X4 X5 X6
1 A B C A B C
2 A F H L H A
3 H X L O H X
4 X Y Z A B C
返回以下错误消息:Warning message:
In (function (..., deparse.level = 1) :
number of columns of result is not a multiple of vector length (arg 2)
这是一个理想的方法,因为它很快,但我不能使用DF
,因为它回收。
是否有办法插入NA
而不是回收,因为向量的长度不同?
到目前为止,我已经通过结合使用for循环和ifelse
语句找到了解决问题的方法。但是,用3轧机遮挡。这种方法需要数年时间!
dat$A <- 0
for(i in seq(1, nrow(dat), 1)) {
print(i)
dat[i, 3] <- ifelse("A" %in% unlist(strsplit(dat[i, 2], " ")), 1, 0)
}
dat$B <- 0
for(i in seq(1, nrow(dat), 1)) {
print(i)
dat[i, 4] <- ifelse("B" %in% unlist(strsplit(dat[i, 2], " ")), 1, 0)
}
这给出了我想要的结果:
dat
orgnr rat A B
1 1 A B C 1 1
2 2 A F H L H 1 0
3 3 H X L O 0 0
4 4 X Y Z A B C 1 1
我搜索了StackOverflow上可以找到的大部分相关问题。这个问题非常接近我的问题:How to convert a list consisting of vector of different lengths to a usable data frame in R?,但我不知道如何使用这种方法实现strsplit
。
答案 0 :(得分:1)
我们可以使用grepl
for循环来完成此任务。 + 0
将列格式TRUE
或FALSE
转换为1或0
for (col in c("A", "B")){
dat[[col]] <- grepl(col, dat$rat) + 0
}
dat
# orgnr rat A B
# 1 1 A B C 1 1
# 2 2 A F H L H 1 0
# 3 3 H X L O 0 0
# 4 4 X Y Z A B C 1 1
如果性能问题,请尝试使用此data.table
方法。
library(data.table)
# Convert to data.table
setDT(dat)
# Create a helper function
dummy_fun <- function(col, vec){
grepl(col, vec) + 0
}
# Apply the function to A and B
dat[, c("A", "B") := lapply(c("A", "B"), dummy_fun, vec = rat)]
dat
# orgnr rat A B
# 1: 1 A B C 1 1
# 2: 2 A F H L H 1 0
# 3: 3 H X L O 0 0
# 4: 4 X Y Z A B C 1 1
答案 1 :(得分:0)
使用Base R:
a=strsplit(dat$rat," ")
b=data.frame(x=rep(dat$orgnr,lengths(a)),y=unlist(a),z=1)
cbind(dat,as.data.frame.matrix(xtabs(z~x+y,b)))
orgnr rat A B C F H L O X Y Z
1 1 A B C 1 1 1 0 0 0 0 0 0 0
2 2 A F H L H 1 0 0 1 2 1 0 0 0 0
3 3 H X L O 0 0 0 0 1 1 1 1 0 0
4 4 X Y Z A B C 1 1 1 0 0 0 0 1 1 1
从这里你可以调用你想要的那些列:
d=as.data.frame.matrix(xtabs(z~x+y,b))
cbind(dat,d[c("A","B")])
orgnr rat A B
1 1 A B C 1 1
2 2 A F H L H 1 0
3 3 H X L O 0 0
4 4 X Y Z A B C 1 1