【问题标题】:is it possible to assign multiple column/values using SET with data.table in R?是否可以在 R 中使用带有 data.table 的 SET 来分配多个列/值?
【发布时间】:2021-05-30 13:22:57
【问题描述】:

是否可以使用“set”将值分配给多个列?

这是一个例子。对于上下文,我想创建两组新的列 - 一组将缺失/NA 值归为 0,另一组指示是否对缺失值进行了估计。第一组列将复制现有组,但使用 0 而不是 NA,并带有后缀“_M0”。第二组将是 0/100,并带有后缀“_MISS”。

我将使用 iris 数据框作为起点。

## create a copy of the iris data frame that i can modify
local_iris <- copy(iris)
## make the local iris copy a data.table
iris.dt <- setDT(local_iris)

没有丢失数据,所以我会添加一些进行测试。

## make some parts of these columns missing, i.e., set to NA
iris.dt[1:5, Sepal.Width := NA][6:10, Sepal.Length := NA]

我在这里只使用“Sepal”列,所以我想保存这些名称并基于它创建新的列名。

## 'grep' returns a list of the positions that meet the criteria; 'grepl' returns a logic vector of the same length as the argument
## using the result of grep as the index/columns of a list seems to do the trick, even if it seems a tiny bit repetitive/clunky
bert <- names(iris.dt)[grep("^Sepal", names(iris.dt))]

## create lists like the original list with new suffixes
bert_M0 <- paste0(bert, "_M0")
bert_MISS <- paste0(bert, "_MISS")

这部分对我来说似乎很清楚,而且进展得很好,但如果有明显(或不那么明显!)的方法来简化它,我愿意接受建议。

关于我的 data.table 和其他对象名称——我在测试时尝试选择不寻常的名称,以确保我没有重复另一个名称。

## the best way to go about this is unclear
## i will settle for 'a' way and worry about 'best' way later
## one approach is to extend the data.table to have the new columns added, and then modify their respective values in place later

## create a copy of the relevant columns
M0<-iris.dt[, .SD, .SDcols = bert]

## rename the columns
setnames(M0, old = bert, new = bert_M0)

## create a new data.table with the copied columns
opus<-cbind(iris.dt, M0)

## this creates a set of indicators and sets all the _MISS columns equal to 0
opus[, (bert_MISS) := 0L]

然后我将使用 set 并循环遍历我的列来重新编码缺失并设置标志/虚拟变量。

但是,这是我的主要问题——是否可以只用一套来做到这一点?还是我需要每列一组?

## try using "set"
for (j in seq_len(length(bert))) { # seq_len(arg) is an alternative way of writing 1:arg
   set(opus, ## the data.table we are operating on
       which(is.na(opus[[bert[j]]])), ## the values of i
       bert_M0[j], ## the column
       0 ## the value
       )
   set(opus, ## the data.table we are operating on
       which(is.na(opus[[bert[j]]])), ## the values of i
       bert_MISS[j], ## the column
       100 ## the value
   )
}

谢谢!

【问题讨论】:

  • 你检查过set函数的手册吗? AFAIU 你的问题应该很容易找到答案。
  • 我做到了。 set 出现在 := 下,但没有一个示例实际使用 set。我还没有看到任何类似set(DT, i, .(col1, col2), (val1, val2) 的示例,但文档并不详尽。
  • 我填写了github.com/Rdatatable/data.table/issues/5031。令我惊讶的是,到目前为止还没有。

标签: r data.table set


【解决方案1】:

我认为这解决了你的问题

for (j in seq_len(length(bert))) set(
  opus,
  which(is.na(opus[[bert[j]]])),
  c(bert_M0[j], bert_MISS[j])
  list(0, 100)
)

您基本上将列名作为字符向量提供,并将值作为列表提供

【讨论】:

  • 是的,这行得通!当我需要使用c(var1, var2) 以及何时可以使用列表时,我仍在努力,比如.(var1, var2)。出于好奇,我检查了.是否可以在值部分使用list,答案是否定的。
  • 手册中解释的所有内容,请参见 ?c 和 ?data.table
猜你喜欢
  • 1970-01-01
  • 2016-07-15
  • 2022-01-05
  • 1970-01-01
  • 2017-05-03
  • 1970-01-01
  • 2020-07-29
  • 1970-01-01
  • 2012-07-25
相关资源
最近更新 更多