如何根据R中元素的长度对列表进行子集化

时间:2014-07-29 18:30:19

标签: r list subset

R我有一个功能(coordinates包中的sp),它为您提供的每个IP地址查找11个数据字段。

我有一个名为ip.addresses的IP列表:

> head(ip.addresses)
[1] "128.177.90.11"  "71.179.12.143"  "66.31.55.111"   "98.204.243.187" "67.231.207.9"   "67.61.248.12"  

注意:可以使用这些或任何其他IP来重现此问题。

所以我使用sapply将该函数应用于该对象:

ips.info     <- sapply(ip.addresses, ip2coordinates)

并获取一个名为ips.info的列表作为我的结果。这一切都很好,但我不能用列表做更多事情,所以我需要将它转换为数据帧。问题是并非所有IP地址都在数据库中,因此一些列表元素只有1个字段,我收到此错误:

> ips.df       <- as.data.frame(ips.info)
Error in data.frame(`128.177.90.10` = list(ip.address = "128.177.90.10",  : 

参数意味着不同的行数:1,0

我的问题是 - &#34;如何删除缺少/不完整数据的元素,或者将此列表转换为每个IP地址有11列和1行的数据框?&#34;

我尝试过几件事。

  • 首先,我尝试编写一个循环,删除长度小于11的元素

    for (i in 1:length(ips.info)){
    if (length(ips.info[i]) < 11){
    ips.info[i] <- NULL}}
    

这会留下一些没有数据的记录,并让其他人说&#34; NULL&#34;,甚至那些带有&#34; NULL&#34; is.null

未检测到
  • 接下来,我尝试使用双方括号进行相同的操作并获取

    Error in ips.info[[i]] : subscript out of bounds
    
  • 我还尝试了complete.cases(),看看它是否有用

    Error in complete.cases(ips.info) : not all arguments have the same length
    
  • 最后,我尝试了for循环的变体,它以length(ips.info[[i]] == 11为条件,并将完整记录写入另一个对象,但不知何故,它会生成ips.info的精确副本< / p>

2 个答案:

答案 0 :(得分:5)

这是使用内置Filter函数

完成此操作的一种方法
#input data
library(RDSTK)
ip.addresses<-c("128.177.90.10","71.179.13.143","66.31.55.111","98.204.243.188",
    "67.231.207.8","67.61.248.15")
ips.info  <- sapply(ip.addresses, ip2coordinates)

#data.frame creation
lengthIs <- function(n) function(x) length(x)==n
do.call(rbind, Filter(lengthIs(11), ips.info))

或者如果您不想使用帮助函数

do.call(rbind, Filter(function(x) length(x)==11, ips.info))

答案 1 :(得分:3)

基于base包的替代解决方案。

  # find non-complete elements
  ids.to.remove <- sapply(ips.info, function(i) length(i) < 11)
  # remove found elements
  ips.info <- ips.info[!ids.to.remove]
  # create data.frame
  df <- do.call(rbind, ips.info)