使用sapply仅获取列表的第一个元素

时间:2014-12-10 15:05:45

标签: r arguments sapply

我在R中读取了一个包含n列的数据框(df< -read.csv(data,as.is = T)),其中一列是这样的char列:

 df$qual
===========

1/5
12/17
...
0/3
9/14

我希望将此列转换为数字向量,仅保留每行的第1个元素。

 df$qual
===========

1
12
...
0
9

我想有更简单的方法(想法欢迎!),但我尝试了一下:

sapply(df$qual,strsplit() ,simplify=T)

现在的问题是我如何/在哪里传递参数split =" /"这样有效吗? R帮助没什么帮助。

提前感谢,p。

3 个答案:

答案 0 :(得分:4)

也许

sapply(strsplit(df$qual,split="/") , "[[", 1)

解释:strsplit生成结果列表,即原始输入中每个字符元素的字符向量。 "[["是调用索引运算符的简便方法,而1表示将附加参数1传递给[[ - 即取第一个元素。另外两种可能更透明的方法来做同样的事情:

sapply(strsplit(df$qual,split="/"), function(x) x[[1]])

sapply(strsplit(df$qual,split="/") , head, 1)

您最后可能需要考虑as.numeric()

答案 1 :(得分:2)

一个带有示例的小替代方案(到目前为止我一直在使用):

myvec <- c('1/5', '12/17', '0/3','111/03') #define a vector

sapply(myvec, function(x) { #using sapply
  a <- gregexpr(pattern='/', x)[[1]][1]  #find location of '/'
  return(substring(x , 1, a-1)) #substring from start and up to 1 position before the '/'
} )

输出(如果您不喜欢名字,可以unname

   1/5  12/17    0/3 111/03 
   "1"   "12"    "0"  "111" 

答案 2 :(得分:2)

你的标题和描述之间有一点点含糊不清,所以无论如何我都会分享这个。

问题1 ,关于如何使用sapply提取每个列表的第一个元素已被@BenBolker充分解决。

问题2 ,关于如何将其他参数传递给sapply似乎没有答案。对此的答案是您将附加参数作为点(...)参数传递给sapply。例如,你可以做到:

sapply(yourvec, strsplit, "/", fixed = FALSE)

在上文中,"/"和“fixed = FALSE”作为strsplitsapply的附加参数传递。请注意,这是一种非常低效的方法,因为您遍历向量并单独拆分每个向量,而strsplit本身已经被向量化。


如果您的问题确实是关于在分隔符之前提取第一部分的有效方法,我确实有一些建议:

选项1 :考虑使用stringi。甚至拆分,转换为矩阵,并提取矩阵的第一列比我在基础R中提出的解决方案更快:

library(string1)
stri_split_fixed(myvec, "/", simplify = TRUE)[, 1]

选项2 :考虑将sub与perl正则表达式一起使用:

sub("(?=/).*", "\\2", myvec, perl = TRUE)

选项3:首选vapplysapply,并通过添加strsplit帮助fixed = TRUE

vapply(strsplit(myvec, split = "/", TRUE), "[[", character(1L), 1)

如果您想比较每种方法的效率,请尝试使用更大的矢量,如下所示:

myvec <- c('1/5', '12/17', '0/3','111/03')
myvec <- c(replicate(25000, myvec))