从strsplit-R之后的嵌套列表中提取第n个元素

时间:2014-09-01 15:18:47

标签: r sapply strsplit

我一直在努力了解如何更好地处理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个观察结果的真实数据以及由此产生的数十个元素,我希望找到更通用的解决方案。

4 个答案:

答案 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