【问题标题】:Remove multiple columns and replace values of columns of dataframe based on condition in R根据R中的条件删除多列并替换数据框列的值
【发布时间】:2016-04-07 05:32:13
【问题描述】:

我有一个包含 4998 列的巨大数据框,列标题是公司的名称。这些列包含股票价格作为列中的值。因此,我想删除股票价格(列中的值)小于 1 的低价股。因此,如果其值小于 1,我想删除整列。此外,数据框中的列值波动,它们低于 1,但随后返回等于或大于 1,在这个场景中,当值低于 1 时,我希望在此列中将其替换为 NA。我曾提到“用另一列中的值替换数据帧多列中的多个值”,但我的情况有点不同。 我说明了数据框的一小部分

df1 <- Price
     Date        A   B       C
    01/01/2000  NA  0.03    0.95
    02/01/2000  NA  0.03    0.95
    03/01/2000  NA  0.03    0.95
    04/01/2000  NA  0.03    0.95
    05/01/2000  5   0.03    0.95
    06/01/2000  6   0.5       1
    07/01/2000  7   0.5       1
    08/01/2000  8   0.5       NA
    09/01/2000  9   0.5       NA

所需的输出数据帧

df2<- df1
Date        A   C
01/01/2000  NA  NA
02/01/2000  NA  NA
03/01/2000  NA  NA
04/01/2000  NA  NA
05/01/2000  5   NA
06/01/2000  6   NA
07/01/2000  7   1
08/01/2000  8   1
09/01/2000  9   NA

非常感谢您的帮助。

【问题讨论】:

  • 如果你把它变成一个更合乎逻辑的数据结构,你的数据会不会更容易管理(包括完成你描述的任务)。将列数减少到 3:“Date”、“CompanyName”、“StockPrice”?在这种情况下,您想要的任务很容易实现。虽然您不需要这样做来找到您的解决方案,但它会使您的 R 代码更加直接和灵活(例如,轻松添加新公司)。
  • @Pete855217 感谢您的建议。我有 3914 行,所以当我融化数据时,我遇到了内存空间问题。
  • 是有这么多行问题还是我在这里遗漏了什么?无论您使用哪种结构,内存要求都大致相同。以这种方式构建数据库的另一个好处是,您在处理它时不需要删除列/数据,并且如果您更改触发器之类的参数(一便士),则不必重新加载(昂贵的)数据文件/cent) 标记删除。 R 的优点之一是它允许在运行脚本时进行高级别的数据结构操作,这是其他过程语言难以实现的!
  • @Pete855217 我跑了几次 melt 但 R 无法完成操作。
  • 好的,看到问题并能理解为什么你会这样!

标签: r if-statement filter dataframe


【解决方案1】:

这是一个类似的方法(也许更矢量化?)

is.na(df[-1]) <- df[-1] < 1 # Convert all values < 1 to NAs.
df[colSums(is.na(df)) != nrow(df)] # Select only the columns that have values.
#         Date  A  C
# 1 01/01/2000 NA NA
# 2 02/01/2000 NA NA
# 3 03/01/2000 NA NA
# 4 04/01/2000 NA NA
# 5 05/01/2000  5 NA
# 6 06/01/2000  6  1
# 7 07/01/2000  7  1
# 8 08/01/2000  8 NA
# 9 09/01/2000  9 NA

或者,第二步可以是

df[c(TRUE, colSums(df[-1], na.rm = TRUE) > 0)]
## OR 
## df[c(TRUE, sapply(df[-1], sum, na.rm = TRUE) > 0)] # as already sugggested

【讨论】:

  • 谢谢你非常简单的案例。代码完美!
  • 是否可以知道已从数据框中删除的列的名称?我真的很感激。
  • 可以names(df)[colSums(is.na(df)) == nrow(df)]。或者只是将新数据集的名称与旧数据集的名称进行比较,例如setdiff(names(df), names(df2))(如果df2 是新数据集)。
  • 感谢您的回答。我可以形成一个向量,即diff_cols &lt;-setdiff(names(df), names(df2)) ,然后使用这个向量删除其他数据帧中的列吗?
  • 是的。仅df[diff_cols] 将生成仅包含这些列的数据集。或类似地,df[names(df2)] 将产生与df2 中具有相同列的数据集。
【解决方案2】:

我会使用两步法。首先,您可以通过以下方式将低于 1 的所有值替换为 NAdf1$Column[df1$Column &lt; 1] &lt;- NA(使用 lapply 在所有列中执行此操作,如下所示)。接下来,我将删除所有仅包含 NA 的列:

df1 <- read.table(textConnection("
    Date        A   B       C
    01/01/2000  NA  0.03    0.95
    02/01/2000  NA  0.03    0.95
    03/01/2000  NA  0.03    0.95
    04/01/2000  NA  0.03    0.95
    05/01/2000  5   0.03    0.95
    06/01/2000  6   0.5       1
    07/01/2000  7   0.5       1
    08/01/2000  8   0.5       NA
    09/01/2000  9   0.5       NA"), header=TRUE, stringsAsFactors=FALSE)

df2 <- df1

## replace values below 1 with NA
df2[, -1] <- lapply(df2[, -1], function(y){y[y < 1] <- NA; y})
# $A
# [1] NA NA NA NA  5  6  7  8  9
#
# $B
# [1] NA NA NA NA NA NA NA NA NA
#
# $C
# [1] NA NA NA NA NA  1  1 NA NA
#

## remove all columns where all values are NA but keep the others
keepColumn <- sapply(df2[, -1], function(y)sum(!is.na(y)) > 0)
#     A     B     C
#  TRUE FALSE  TRUE

## keep Date column and all the other with values greater than 1
df2[, c(TRUE, keepColumn)]
#         Date  A  C
# 1 01/01/2000 NA NA
# 2 02/01/2000 NA NA
# 3 03/01/2000 NA NA
# 4 04/01/2000 NA NA
# 5 05/01/2000  5 NA
# 6 06/01/2000  6  1
# 7 07/01/2000  7  1
# 8 08/01/2000  8 NA
# 9 09/01/2000  9 NA

【讨论】:

  • 是否可以知道已从数据框中删除的列的名称?我真的很感激。
  • 类似colnames(df1)[c(FALSE, !keepColumns)]?
猜你喜欢
  • 2016-04-26
  • 1970-01-01
  • 2021-08-06
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 2022-07-06
  • 1970-01-01
  • 2018-11-25
相关资源
最近更新 更多