【问题标题】:How to use lapply to remove columns with too many missing values in a list in R?如何使用 lapply 删除 R 列表中缺失值过多的列?
【发布时间】:2017-04-04 18:15:47
【问题描述】:

我有一个名为ls.df.val.dcas 的数据框列表。每个数据框都有不同的列,其中一些缺失值为 NA。我想在列表中使用lappy(),这样我就可以删除那些超过 X %(例如 40%)的值是 NA 的列。为了让您了解列表中的数据框的外观,我正在展示一个示例:

 $ SK_VALUES_IMV_EU28_INTRA  :'data.frame': 74 obs. of  65 variables:
  ..$ PERIOD  : Date[1:74], format: "2010-01-01" "2010-02-01" "2010-03-01" "2010-04-01" ...
  ..$ 2207    : num [1:74] 1078759 1850083 1872924 1038070 626471 ...
  ..$ 2208    : num [1:74] 3329179 7061890 1351550 1371469 1557605 ...
  ..$ 220710  : num [1:74] 1030704 1804495 1831958 972263 574855 ...
  ..$ 220720  : num [1:74] 48055 45588 40966 65807 51616 ...
  ..$ 220820  : num [1:74] 380843 1014933 71804 126348 138138 ...
  ..$ 220830  : num [1:74] 380007 459653 155033 205879 297446 ...
  ..$ 220840  : num [1:74] 41561 88449 31549 60768 117534 ...
  ..$ 220850  : num [1:74] 94483 340439 44949 32949 37550 ...
  ..$ 220860  : num [1:74] 371217 728521 143974 179311 254546 ...
  ..$ 220870  : num [1:74] 731231 1374532 228087 227772 230129 ...
  ..$ 22082014: num [1:74] NA 2531 1776 NA NA ...
$ RO_VALUES_IMV_EU28_EXTRA  :'data.frame':  74 obs. of  44 variables:
  ..$ PERIOD  : Date[1:74], format: "2010-01-01" "2010-02-01" "2010-03-01" "2010-04-01" ...
  ..$ 2207    : num [1:74] NA NA NA NA NA 5 NA NA NA NA ...
  ..$ 2208    : num [1:74] 312035 840540 315008 884357 100836 ...
  ..$ 220710  : num [1:74] NA NA NA NA NA 5 NA NA NA NA ...
  ..$ 220720  : num [1:74] NA NA NA NA NA NA NA NA NA NA ...
  ..$ 220820  : num [1:74] 3570 698 483 1087 1802 ...

我的不完整解决方案是基于计算每个数据框每列中的 NA 数量并计算 NA 的百分比。然后删除百分比超过 X% 的那些列。

# Counting the number of NA
ls.Nan <- lapply(ls.df.val.dcas, function(x) colSums(!is.na(x)))
# Calculating the lengths of all column
ls.size <- lapply(ls.df.val.dcas, function(x) dim(x))

# we want the first element of size which shows the number of rows.
ls.percen <- mapply(function(x,y) x/y[1] , x=ls.Nan, y=ls.size)
# keeping those columns that have more than half of the data on that category

mis.list <- sapply(ls.df.val.dcas, "]]" sapply(ls.percen, function(x) x >= NPI))

运行最后一行时出现以下错误。

Error: unexpected symbol in "mis.list <- sapply(ls.df.val.dcas, "]]" sapply"

最后我也喜欢将所有这些函数合并为一个函数,然后使用 lapply 一次。但是现在,我正在努力理解应用于数据帧列表的 lapply 索引系统。如果有人可以通过示例演示如何使用具有不同列表粒度的 lapply ,那就太好了。例如,当您想要更改列表的元素或列表中的数据框或列表的数据框中的列时,应如何编写函数。

编辑 鉴于下面关于忘记在“]]”之后加逗号的评论。我更正了代码,但仍然出现错误

> mis.list <- sapply(ls.df.val.dcas, "]]", sapply(ls.percen, function(x) x >= NPI))
Error in get(as.character(FUN), mode = "function", envir = envir) : 
  object ']]' of mode 'function' was not found

顺便说一下,NPI 只是列中 NA 的百分比阈值。例如,我将其设置为 NPI= 0.35

由于我怀疑该错误与我的数据结构有关,因此我添加了有关 ls.percen 结构的更多信息。

> str(ls.percen)
    List of 69
     $ AT_VALUES_IMV_EU28_EXTRA  : Named num [1:59] 1 0.635 1 0.378 0.338 ...
      ..- attr(*, "names")= chr [1:59] "PERIOD" "2207" "2208" "220710" ...
     $ AT_VALUES_IMV_EU28_INTRA  : Named num [1:67] 1 0.986 0.986 0.986 0.986 ...
      ..- attr(*, "names")= chr [1:67] "PERIOD" "2207" "2208" "220710" ...
     $ BE_VALUES_IMV_EU28_EXTRA  : Named num [1:57] 1 1 1 1 0.365 ...
      ..- attr(*, "names")= chr [1:57] "PERIOD" "2207" "2208" "220710" ...
     $ BE_VALUES_IMV_EU28_INTRA  : Named num [1:69] 1 0.986 0.986 0.986 0.986 ...
      ..- attr(*, "names")= chr [1:69] "PERIOD" "2207" "2208" "220710" ...

【问题讨论】:

    标签: r list indexing lapply sapply


    【解决方案1】:

    可能是一个简单的错字(而不是索引问题):该消息说您缺少逗号,它可能应该是:

    mis.list <- sapply( ls.df.val.dcas, "]]", sapply(ls.percen, function(x) x >= NPI))
    

    我们没有看到“NPI”的定义。将前两个“lapply”调用合并(并返回所需的短 df 列表)可能更简单:

    mis.lst <- lapply( ls.df.val.dcas, 
                      function(x) x[ , colSums(!is.na(x))/nrow(x) > .40 ] )
    

    对于“[”的两个参数版本,您可以在“j”位置使用逻辑索引。

    【讨论】:

    • 感谢您的回答。即使我纠正了错字并添加了逗号,第一行代码仍然不起作用。建议的第二行代码完美运行。
    • 我能再问你一个问题吗?我现在如何使用应用系列函数之一将列表的所有数据框和列中的 NA 替换为零?以下代码行不起作用: basic.lst
    • 这是一个在 SO 上被多次询问的问题的副本。您需要提问之前进行搜索。
    • 我已经完成了搜索。我知道数据框的解决方案,但是当涉及到数据框列表时,它根本不起作用。例如,我也尝试了这行代码:basic.lst
    • 我对你的第一个问题进行了猜测。为此,制作一个工作测试用例应该非常简单。如果确实没有重复,您应该发布另一个问题..
    猜你喜欢
    • 2018-01-12
    • 2015-05-30
    • 2021-01-07
    • 2018-03-18
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多