【问题标题】:How to delete columns from a data.table based on values in column如何根据列中的值从 data.table 中删除列
【发布时间】:2015-06-15 19:27:40
【问题描述】:

背景

我有一些财务数据(1.5 年 SP500 股票),我使用 data.table 包将其处理成宽格式。在 Datacamp 上完成整个 data.table 课程之后,我开始掌握基础知识,但是在搜索了几个小时之后,我不知道如何做到这一点。

问题

数据包含包含每只股票财务数据的列。我需要删除包含两个连续 NA 的列。

我的猜测是我必须使用rle()lapply() 来查找连续值并使用DT[,x:= NULL]) 来删除列。

我读到rle() 不适用于 NA,因此我将它们改为 Inf。 我只是不知道如何组合这些功能,以便我可以有效地删除我拥有的 460 中的几列。

使用data.table 的答案会很棒,但任何运作良好的东西都非常感谢。

或者,我很想知道如何删除包含至少 1 个 NA 的列

示例数据

> test[1:5,1:5,with=FALSE]
         date     10104     10107     10138     10145
1: 2012-07-02  0.003199       Inf  0.001112 -0.012178
2: 2012-07-03  0.005873  0.006545  0.001428       Inf
3: 2012-07-05       Inf -0.001951 -0.011090       Inf
4: 2012-07-06       Inf -0.016775 -0.009612       Inf
5: 2012-07-09 -0.002742 -0.006129 -0.001294  0.005830
> dim(test)
[1] 377 461

期望的结果

         date     10107     10138
1: 2012-07-02       Inf  0.001112
2: 2012-07-03  0.006545  0.001428
3: 2012-07-05 -0.001951 -0.011090
4: 2012-07-06 -0.016775 -0.009612
5: 2012-07-09 -0.006129 -0.001294

PS。这是我的第一个问题,我已尝试遵守规则,如果需要更改任何内容,请告诉我。

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    这是rle 版本:

    dt[, sapply(dt, function(x)
           setDT(rle(is.na(x)))[, sum(lengths > 1 & values) == 0]), with = F]
    

    如果您愿意,也可以将 is.na 替换为 is.infinite

    【讨论】:

      【解决方案2】:

      要检测和删除包含至少一个 NA 的列,您可以尝试以下操作

      data = data.frame(A=c(1,2,3,4,5), B=c(2,3,4,NA,6), C=c(3,4,5,6,7), D=c(4,5,NA,NA,8))
      
      colsToDelete = lapply(data, FUN = function(x){ sum(is.na(x)) >= 1 })
      
      data.formatted = data[,c(!unlist(colsToDelete))]
      

      【讨论】:

      • 如果我理解正确的话,多个NA 条目是可以接受的,但是,连续的NA 条目是不能接受的。
      • 我试图回答问题的备用部分“或者我很想知道如何删除包含至少 1 个 NA 的列”
      • 你知道这是一个data.table 的问题,对吧?我在这里找不到任何data.table 语法...
      • @DavidArenburg,@blakeoft,我是 R 新手(写我的论文),我确实学习了 data.table 来重塑数据。我对基本 R 解决方案很满意,因为我时间紧迫,尽管我很想知道是否有 data.table 解决方案。我会相应地编辑问题。
      • @SKG 谢谢你帮我解决这个问题。对data.table 非常陌生。
      【解决方案3】:

      显然问题是发现 连续 缺失。 首先,根据缺失的NA 创建一个矩阵TRUE/FALSE。使用该矩阵将每一行与下一行进行比较。保留原始矩阵中的列colSums == 0

      试试这个:

      Missing.Mat <- apply(test, 2, is.na)
      Consecutive.Mat <- Missing.Mat[-nrow(Missing.Mat),] * Missing.Mat[-1,]
      Keep.Cols <- colSums(Consecutive.Mat) == 0
      
      test[,Keep.Cols]
      

      【讨论】:

      • 若要删除至少包含一个NA 的列,请改用Keep.Cols &lt;- colSums(Missing.Ma)==0
      • 谢谢亚伦,这太棒了。因为我使用 data.table 包,所以最后一行必须是 test[,Keep.Cols, with=FALSE] 我完全忽略了只关注 data.table 的重点。我是否正确理解您通过将 Missing.Mat 的偏移版本相乘来制作 Consecutive.Mat,其中两个连续会“重叠”?
      • 没错。这个解决方案对你还有效吗?
      • 我认为更多data.tableish 版本会类似于setDT(df1)[, names(Filter(isTRUE, lapply(.SD, function(x) sum(x[-1L] == x[-.N]) == 0)))] ; df1[, names(indx), with = FALSE]
      • @StevenBeaupré 这只是对这个答案的轻微修改,因为我根本无法在这里追踪任何 data.table 语法。
      【解决方案4】:

      这就是我想出的。它在向量y(即1:length(column))上调用rle,除非列的对应元素是Inf,在这种情况下,y 中的对应值为零。然后它检查是否有任何运行大于 1。

      keep <- c(date = T, apply(dat[, -1], 2,
                    function(x) {
                      y <- 1:length(x)
                      y[!is.finite(x)] <- 0
                      return(!any(rle(y)$lengths > 1))
                    }))
      
      dat2 <- dat[, keep]
      dat2
      #         date    X10107    X10138
      # 1 2012-07-02       Inf  0.001112
      # 2 2012-07-03  0.006545  0.001428
      # 3 2012-07-05 -0.001951 -0.011090
      # 4 2012-07-06 -0.016775 -0.009612
      # 5 2012-07-09 -0.006129 -0.001294
      

      请注意,列名前面带有 read.table 的“X”。

      现在,数据的输入:

      dat <- structure(list(date = c("2012-07-02", "2012-07-03", "2012-07-05", 
      "2012-07-06", "2012-07-09"), X10104 = c(0.003199, 0.005873, Inf, 
      Inf, -0.002742), X10107 = c(Inf, 0.006545, -0.001951, -0.016775, 
      -0.006129), X10138 = c(0.001112, 0.001428, -0.01109, -0.009612, 
      -0.001294), X10145 = c(-0.012178, Inf, Inf, Inf, 0.00583)), .Names = c("date", 
      "X10104", "X10107", "X10138", "X10145"), class = "data.frame", row.names = c(NA, 
      -5L))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-06
        • 2021-06-01
        • 2019-07-10
        • 1970-01-01
        • 2012-05-21
        • 2023-04-08
        • 2022-01-08
        • 1970-01-01
        相关资源
        最近更新 更多