我一直在努力了解如何更好地处理strsplit
的输出。我经常有这样的数据,我想分开:
mydata <- c("144/4/5", "154/2", "146/3/5", "142", "143/4", "DNB", "90")
#[1] "144/4/5" "154/2" "146/3/5" "142" "143/4" "DNB" "90"
分割后,结果如下:
strsplit(mydata, "/")
#[[1]]
#[1] "144" "4" "5"
#[[2]]
#[1] "154" "2"
#[[3]]
#[1] "146" "3" "5"
#[[4]]
#[1] "142"
#[[5]]
#[1] "143" "4"
#[[6]]
#[1] "DNB"
#[[7]]
#[1] "90"
我从strsplit帮助指南得知最终的空字符串不会产生。因此,根据&#34; /&#34;的数量,我的每个结果中都会有1,2或3个元素。分开
获得第一个元素非常简单:
sapply(strsplit(mydata, "/"), "[[", 1)
#[1] "144" "154" "146" "142" "143" "DNB" "90"
但我不知道如何获得第2,第3 ......当每个结果中存在这些不等数量的元素时。
sapply(strsplit(mydata, "/"), "[[", 2)
# Error in FUN(X[[4L]], ...) : subscript out of bounds
我希望从一个有效的解决方案返回,如下:
#[1] "4" "2" "3" "NA" "4" "NA" "NA"
这是一个相对较小的例子。我可以很容易地对这些数据做一些for循环,但是对于运行strsplit的1000个观察结果的真实数据以及由此产生的数十个元素,我希望找到更通用的解决方案。
答案 0 :(得分:4)
(至少关于1D向量)[
似乎在&#34; i&gt;时返回NA
长度(X)&#34;而[[
会返回错误。
x = runif(5)
x[6]
#[1] NA
x[[6]]
#Error in x[[6]] : subscript out of bounds
挖掘一下,do_subset_dflt
(即[
)来电ExtractSubset
我们注意到当想要的索引(&#34; ii&#34;)是&#34;&gt; ;长度(X)&#34;返回NA
(稍微修改为干净):
if(0 <= ii && ii < nx && ii != NA_INTEGER)
result[i] = x[ii];
else
result[i] = NA_INTEGER;
另一方面do_subset2_dflt
(即[[
)如果想要的索引(&#34;偏移&#34;)是&#34;&gt;则返回错误。长度(X)&#34; (修改了一下要干净):
if(offset < 0 || offset >= xlength(x)) {
if(offset < 0 && (isNewList(x)) ...
else errorcall(call, R_MSG_subs_o_b);
}
其中#define R_MSG_subs_o_b _("subscript out of bounds")
(我不确定上面的代码段,但根据他们的回报,它们似乎相关)
答案 1 :(得分:3)
试试这个:
> read.table(text = mydata, sep = "/", as.is = TRUE, fill = TRUE)
V1 V2 V3
1 144 4 5
2 154 2 NA
3 146 3 5
4 142 NA NA
5 143 4 NA
6 DNB NA NA
7 90 NA NA
如果您想将DNB
视为NA,请添加参数na.strings="DNB"
。
如果您真的想使用strsplit
,请尝试以下方法:
> do.call(rbind, lapply(strsplit(mydata, "/"), function(x) head(c(x,NA,NA), 3)))
[,1] [,2] [,3]
[1,] "144" "4" "5"
[2,] "154" "2" NA
[3,] "146" "3" "5"
[4,] "142" NA NA
[5,] "143" "4" NA
[6,] "DNB" NA NA
[7,] "90" NA NA
注意:使用alexis_laz的观察结果x[i]
如果NA
不在i
中,则1:length(x)
会返回t(sapply(strsplit(mydata, "/"), "[", 1:3))
,可以简化上面的最后一行代码到:
{{1}}
答案 2 :(得分:1)
您可以使用regex
(如果允许)
library(stringr)
str_extract(mydata , perl("(?<=\\d/)\\d+"))
#[1] "4" "2" "3" NA "4" NA NA
str_extract(mydata , perl("(?<=/\\d/)\\d+"))
#[1] "5" NA "5" NA NA NA NA
答案 3 :(得分:0)
您可以在sapply
内指定长度,从而导致NA
当前长度短于指定的长度。
s <- strsplit(mydata, "/")
sapply(s, function(x) { length(x) <- 3; x[2] })
# [1] "4" "2" "3" NA "4" NA NA
然后,您可以使用mapply
m <- max(sapply(s, length))
mapply(function(x, y, z) { length(x) <- z; x[y] }, s, 2, m)
# [1] "4" "2" "3" NA "4" NA NA