我有一个载体
vec <- c("ab", "#4", "gw", "#29", "mp", "jq", "#35", "ez")
通常遵循两个不同字符串序列之间交替的模式(第一个序列全部按字母顺序排列,第二个序列是数字,符号为#)。
但是,有些情况下不会显示#字词:所以在上面mp
和jq
之间,然后再在ez
之后。我想定义一个填补空白的功能&#34;使用字符串#
,以便输出:
[1] "ab" "#4" "gw" "#29" "mp" "#" "jq" "#35" "ez" "#"
然后我将转换为数据框
V1 V2
1 ab #4
2 gw #29
3 mp #
4 jq #35
5 ez #
到目前为止,我的尝试相当笨重,并且依赖于遍历向量并填补空白。我有兴趣看到更优雅的解决方案。
我的解决方案
greplSpace <- function(pattern, replacement, x){
j <- 1
while( j < length(x) ){
if(grepl(pattern, x[j+1]) ){
j <- j+2
} else {
x <- c( x[1:j], replacement, x[(j+1):length(x)] )
j <- j+2
}
}
if( ! grepl(pattern, tail(x,1) ) ){ x <- c(x, replacement) }
return(x)
}
library(magrittr)
vec <- c("ab", "#4", "gw", "#29", "mp", "jq", "#35", "ez")
vec %>% greplSpace("#", "#", . ) %>%
matrix(ncol = 2, byrow = TRUE) %>%
as.data.frame
答案 0 :(得分:5)
答案 1 :(得分:1)
您可以使用Base R:
首先将向量折叠为字符串,同时在需要时替换#
。
然后只需使用read.csv
vec1=gsub("([a-z]),\\s*([a-z])|$","\\1,#,\\2",toString(vec))
read.csv(text=gsub("(#.*?),","\\1\n",vec1),h=F)
V1 V2
1 ab #4
2 gw #29
3 mp #
4 jq #35
5 ez #
说明:
toString
,
即[a-z],\s*[a-z]
或结尾即|$
两侧都有字母,则会插入#
。#
之后创建换行符,并将数据作为表格读入你也可以这样做:
a=read.csv(h=F,text=toString(sub("([a-z]+)","\n\\1",vec)),na=c(" ",""))[1:2]
a
V1 V2
1 ab #4
2 gw #29
3 mp <NA>
4 jq #35
5 ez <NA>
data.frame(replace(as.matrix(a),is.na(a),"#"))
V1 V2
1 ab #4
2 gw #29
3 mp #
4 jq #35
5 ez #
答案 2 :(得分:1)
以下是base R
选项split
。通过检查每个字符串中的“#”来创建逻辑索引,通过此分组变量将累积和和split
原始向量转换为list
('lst')。对于那些没有两个(最大长度)元素的list
元素,最后通过NA
赋值length<-
。然后,rbind
,将list
个元素分成两列matrix
。如果需要,请将这些NA转换为#
lst <- split(vec, cumsum(!grepl("#", vec)))
out <- do.call(rbind, lapply(lst, `length<-`, max(lengths(lst))))
out[,2][is.na(out[,2])] <- "#" #not recommended though
out
# [,1] [,2]
#1 "ab" "#4"
#2 "gw" "#29"
#3 "mp" "#"
#4 "jq" "#35"
#5 "ez" "#"
如果我们需要as.data.frame
输出
data.frame
换行
答案 3 :(得分:1)
另一种base
可能性:
do.call(rbind, tapply(vec, cumsum(!grepl("^#", vec)), FUN = function(x){
if(length(x) == 1) c(x, "#") else x}))
# [,1] [,2]
# 1 "ab" "#4"
# 2 "gw" "#29"
# 3 "mp" "#"
# 4 "jq" "#35"
# 5 "ez" "#"
说明:
检查vec
中的元素是否以#
开头,并取消它:!grepl("^#", vec)
;创建一个逻辑向量。
通过将cumsum
应用于逻辑向量来创建分组变量(注意:1&amp; 2类似于@akrun)。
使用tapply
将函数应用于由分组变量定义的vec
的每个子集。检查if
length
是1
。#
。如果是这样,请使用尾随else
,if(length(x) == 1) c(x, "#") else x
填充,只返回子集:do.call(rbind,
将结果列表按行绑定在一起:# create a row index
ri <- cumsum(!grepl("^#", vec))
# create a column index
ci <- ave(ri, ri, FUN = seq_along)
# create an empty matrix of desired dimensions
m <- matrix(nrow = max(ri), ncol = 2)
# assign 'vec' to matrix at relevant indices
m[cbind(ri, ci)] <- vec
# replace NA with '#'
m[is.na(m)] <- "#"
另一个:
data.table
使用library(data.table)
d <- data.table(vec)
d[ , g := cumsum(!grepl("^#", vec))]
dcast(d, g ~ rowid(g), value.var = "vec", fill = "#")
# g 1 2
# 1: 1 ab #4
# 2: 2 gw #29
# 3: 3 mp #
# 4: 4 jq #35
# 5: 5 ez #
。如上所述创建分组变量,并从长到宽重塑。
<input type="button" value="startCut" onclick="moveMap()">