【问题标题】:Applying function to a subset of columns depending on a conditional根据条件将函数应用于列的子集
【发布时间】:2017-03-10 14:24:44
【问题描述】:

我有一个大的data.table,有数百列和数千行。大多数列都包含像 X/Y 或 Y/Z 等比率的数值。

我需要翻转一些这些比率,以便它们从 Y/Z -> Z/Y 转换。我对这些列的唯一指示是包含子字符串“x/y”或“y/z”的列名。

我可以使用grepl 获取与“y/z”匹配的列,但我不确定如何使用apply/lapply 等的逻辑值数组。我意识到我可以提取列(通过逻辑索引或.SDcols)并转换它们,但我不想丢弃/忽略剩余的列。

最后,我尝试过这样的事情

flipcols <- grepl("Y/Z", names(sites))
sites.new <- sites[, , lapply(.SD, function(x) 1/x), .SDcols = flipcols]

但是sitessites.new没有区别,应该转换的列没有转换,对应列之间的总和差为0。

建议?

编辑:在@akrun 之后,我尝试了 := 运算符,但它会导致以下其他问题:

# I think this fails because flipcols is a logical vector and not a list of names or indices
> sites.new <- sites[, (flipcols) := lapply(.SD, function(x) 1/x), .SDcols = flipcols]
Error in `[.data.table`(sites, , `:=`((flipcols), lapply(.SD, function(x) 1/x)),  : 
  LHS of := isn't column names ('character') or positions ('integer' or 'numeric')


# and this seems to fail because .SDcols seems to lock the data in read-only mode
> sites.new <- sites[, which(flipcols) := lapply(.SD, function(x) 1/x), .SDcols = flipcols]
Error in assign(ii, SDenv$.SDall[[ii]], SDenv) : 
  cannot change value of locked binding for '.SD'

EDIT2:这是一个最小示例,目标是转换与“Y/Z”模式匹配的列(此处最小示例中的第二个和第四个), 保持其他列不变并保留部分结果。

> dt <- data.table(matrix(rnorm(25), 5,5))
> names(dt) <- c("X/Y_1", "Y/Z_1", "X/Y_2", "Y/Z_2", "X/Y_3")
> dt
        X/Y_1       Y/Z_1       X/Y_2      Y/Z_2      X/Y_3
1:  1.5972490 -0.01763484  1.10745607 -0.1416583 -0.4632829
2:  0.6629621 -0.82719204 -1.68214956  0.6145526 -0.8169235
3: -0.7491393 -0.05290791  0.63935066  1.0665537 -1.9107424
4: -0.6804972 -0.40107880 -0.01030063  1.4566075 -0.6866042
5:  0.2505391 -0.29091850 -1.95926987  0.8733446  1.3909565

【问题讨论】:

  • lapply 之前有两个,,,应该是sites[, lapply(.SD, ..。 data.table 的一般格式,即dt[i, j, by]
  • @akrun 是正确的,但是通过删除逗号,我有效地只选择了我操作的列。我还需要返回未触及的列
  • 在这种情况下,使用赋值:=sites[, (flipcols) := lapply(.SD, function(x) 1/x), .SDcols = flipcols]
  • @akrun 你是什么意思?我应该如何使用运算符?
  • 你在这里弄错了逗号。在问太多问题之前,请在你的帖子中放一个具体的例子,这样 akrun 可以根据上下文来说明他的答案。

标签: r data.table lapply


【解决方案1】:

按照你的例子,

library(data.table)
dt <- data.table(matrix(rnorm(25), 5,5))
names(dt) <- c("X/Y_1", "Y/Z_1", "X/Y_2", "Y/Z_2", "X/Y_3")
dt
         X/Y_1      Y/Z_1      X/Y_2       Y/Z_2       X/Y_3
1: -0.09845804 -0.6455857  0.2259012  1.26772833  1.14451170
2: -1.22147654  1.7643609  0.5310762 -0.46869816 -0.58761886
3: -0.61469060  1.2323381 -0.4028002  0.99903384  0.01650606
4: -0.80805337  0.2733621 -0.2855663 -0.02166544  0.59398122
5: -0.68398344  0.2891335 -0.5004021  2.12063769  0.40474155

我会先匹配目标列

sd.cols <- grep("Y/Z", names(dt), value = T)

然后,只需通过引用更改列,使用标准 data.table 表示法。

dt[ , (sd.cols) := lapply(.SD, function(x){x^-1}), .SDcols = sd.cols ]
         X/Y_1      Y/Z_1      X/Y_2       Y/Z_2       X/Y_3
1: -0.09845804 -1.5489811  0.2259012   0.7888125  1.14451170
2: -1.22147654  0.5667775  0.5310762  -2.1335693 -0.58761886
3: -0.61469060  0.8114656 -0.4028002   1.0009671  0.01650606
4: -0.80805337  3.6581513 -0.2855663 -46.1564513  0.59398122
5: -0.68398344  3.4586094 -0.5004021   0.4715563  0.40474155

【讨论】:

    猜你喜欢
    • 2019-01-14
    • 1970-01-01
    • 2014-08-03
    • 2015-03-15
    • 2014-08-05
    • 2021-11-17
    • 1970-01-01
    • 2013-11-19
    • 1970-01-01
    相关资源
    最近更新 更多