【问题标题】:Getting only 1st elements of list using sapply使用 sapply 仅获取列表的第一个元素
【发布时间】:2014-12-10 15:05:44
【问题描述】:

我在 R 中读取了一个包含 n 列的数据框 (df

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

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

我想将此列转换为数字向量,只保留每行的第一个元素。

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

1
12
...
0
9

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

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

现在的问题是我如何/在哪里传递参数 split="/" 以便它起作用? R 帮助没有多大帮助。

提前致谢,p.

【问题讨论】:

  • 对使用该网站近一年的人说奇怪的话 :),但它就是这样。您可能应该查看tour 以了解该站点的工作方式。通常,当您认为某个答案已经解决了您的问题(并且只有这样)时,最好将该答案标记为已接受,以便其他用户也可以从中受益。您可以通过单击答案旁边的绿色勾号来接受答案。接受答案不是强制性的,但当答案解决了问题时,鼓励接受。
  • 我以友好的方式说上述内容,绝不是要冒犯你或告诉你:)
  • 我会支持@LyzanderR 的评论 - 11 个问题,其中 10 个已回答,没有被接受的答案被认为是低接受率(你不是要求接受任何答案,特别是如果您认为它们没有帮助,但被认为是礼貌)
  • 今天才知道。 thnx 用于定位。

标签: r arguments sapply


【解决方案1】:

也许

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()

【讨论】:

  • 无论如何可能是最好的选择。
【解决方案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" 

【讨论】:

  • 也有效。我得到这个解决方案很好;我的问题主要是向 sapply 传递参数。
  • 感谢您的评论。很高兴它有帮助:)
【解决方案3】:

你的标题和描述之间有点模棱两可,所以我还是会分享这个。

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

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

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

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


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

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

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

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

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

选项 3:首选vapply 而不是sapply,并通过添加fixed = TRUE 来帮助strsplit

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

如果您想比较每种方法的效率,请在更大的向量上尝试一下,如下所示:

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

【讨论】:

  • 这么好的答案!我的问题是关于 sapply 的论点,现在清楚了。我意识到'strsplit'是矢量化的,所以你可以这样做:strsplit(df$colname) 它会工作。我不知道如何只保留第一个元素,以及如何摆脱数据框中的“列表”。再效率,你的方法最好。
猜你喜欢
  • 2016-12-31
  • 2019-04-19
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 2021-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多