【问题标题】:How to sequentially add conditioning in a for loop in R如何在 R 的 for 循环中按顺序添加条件
【发布时间】:2019-12-15 22:14:56
【问题描述】:

我想运行一个for循环说x次,例如,我想测试除此之外的所有先前数据是否为> 0.5,而这是< 0.5,因此对于x = 1,我将测试是否dt[code_a > 0.5 & code_b <0.5,]。对于x = 2,我想测试dt[code_a >0.5 & code_b >0.5 & code_c <0.5,] 等。然后我希望它只给出测试的列和id 列,但这很简单我可以只做dt_l <- list() 然后@987654329 @在for loop中。

这是样本数据

a <- runif(5)
b <- runif(5)
c <- runif(5)
d <- runif(5)
e <- runif(5)
id <- 1:5
dt <- data.table("ID" = id, "code_a" = a, "code_b" = b, "code_c" = c, "code_d" = d, "code_e" = e)
   ID    code_a    code_b     code_c    code_d    code_e
1:  1 0.7224877 0.4729436 0.88773445 0.3081957 0.0379483
2:  2 0.7629343 0.9226372 0.06482454 0.7126673 0.4047996
3:  3 0.1423318 0.9317842 0.77045695 0.3122390 0.5333623
4:  4 0.9592109 0.8323915 0.30976919 0.3952811 0.1727833
5:  5 0.7556562 0.4359695 0.99086645 0.6474944 0.0738418

预期输出

dt_l[[1]]
   ID    code_a    code_b 
1:  1 0.7224877 0.4729436  
2:  5 0.7556562 0.4359695 
dt_l[[2]]
   ID    code_a    code_b     code_c 
1:  2 0.7629343 0.9226372 0.06482454 
2:  4 0.9592109 0.8323915 0.30976919 
dt_l[[3]]
   ID    code_a    code_b     code_c    code_d 
No rows

【问题讨论】:

  • 在使用随机数据时请使用固定的随机种子(set.seed(...)),以使结果可重现;否则我们将无法重新创建您的示例输入和输出。

标签: r datatable


【解决方案1】:

我们循环遍历lapply中的列索引,对数据集进行子集化,根据帖子中的逻辑创建逻辑条件,对数据集进行子集化

library(data.table)
lapply(3:5, function(i)  {
      i1 <- seq(i)
      i2 <- dt[, Reduce(`&`, lapply(.SD[, -ncol(.SD), with = FALSE], `>`, 0.5)) & 
        .SD[[ncol(.SD)]] < 0.5,.SDcols = i1[-1]
   dt[i2, .SD, .SDcols = i1]
   })
#[[1]]
#   ID    code_a    code_b
#1:  1 0.7224877 0.4729436
#2:  5 0.7556562 0.4359695

#[[2]]
#   ID    code_a    code_b     code_c
#1:  2 0.7629343 0.9226372 0.06482454
#2:  4 0.9592109 0.8323915 0.30976919

#[[3]]
#Empty data.table (0 rows and 5 cols): ID,code_a,code_b,code_c,code_d

【讨论】:

  • 它工作得很好,但是我想多了解一点,因为我还不太熟悉.SD atm。所以对于项目 3 到 5(对应于我想成为 &lt;0.5 的最后一个元素),我们应用函数使得 i1 将是取决于 3:5 的数字序列。此序列用于表示我想要包含的列 i2 返回一个 logical vctor,如果行满足我给定的条件,则会给出。
  • 条件首先被设置,lapply(.SD[, -ncol(.SD), with = FALSE] 给出了数据的子集,它只产生所有内容,但最后一列 lapply (不确定这是如何工作的)为每个给出&gt;0.5柱子?然后Reduce("&amp;") 将它们全部连接在一起,但是为什么&amp;在前面呢?这也是如何工作的,因为它不会产生类似&amp;code_a&gt;0.5&amp;code_b&gt;0.5 等的东西吗?
  • 接着下一个条件,SD的最后一列.SDcols = i1[-1]做什么? dt[i2, .SD, .SDcols = i1] 仅显示i2 中给出的真实陈述,但是,我不确定其他参数的含义。感谢您的帮助。
  • @Kazusa12345 在这里,lapply(.SD[, -ncol(.SD), with = FALSE], .. 循环遍历由.SDcols 指定的列,除了我们应用&gt; 条件的最后一列。由于这些列不止一列,因此将逻辑向量的list 组合在一起的一种方法是将Reduce&amp; 组合在一起(您的帖子描述了在&lt; 0.5 条件下与&amp; 组合,这是它们的组合最后一列条件&gt; 0.5
  • @Kazusa12345 .SD[[ncol(.SD)]].SDcols 中最后一列的子集,请注意seq(2)seq(3).SDcols 中返回来自1 的数字,即1:2、1:3 , 我们用[-1] 去掉 1,这样 ID 就不是比较的一部分了
【解决方案2】:

这是一种不同的方法,在性能方面可能不如akrun's approach 有效,但我更容易理解。

这里的想法是将数据从宽格式重塑为长格式。在长格式中,列名显示为数据项,这有助于以更直接的方式表达条件,恕我直言。

library(data.table)
library(magrittr)
long <- melt(dt, "ID")
lvl <- levels(long$variable)
lapply(
  seq_along(lvl)[-1], 
  function(i) {
    long[(variable %in% lvl[seq(i-1)] & value > 0.5) | (variable == lvl[i] & value < 0.5)] %>% 
    dcast(ID ~ variable) %>% 
    na.omit()
  }
)
[[1]]
   ID    code_a    code_b
1:  1 0.7224877 0.4729436
2:  5 0.7556562 0.4359695

[[2]]
   ID    code_a    code_b     code_c
1:  2 0.7629343 0.9226372 0.06482454
2:  4 0.9592109 0.8323915 0.30976919

[[3]]
Empty data.table (0 rows and 5 cols): ID,code_a,code_b,code_c,code_d

[[4]]
Empty data.table (0 rows and 6 cols): ID,code_a,code_b,code_c,code_d,code_e

说明

待完成

数据

library(data.table)
dt <- fread ("rn   ID    code_a    code_b     code_c    code_d    code_e
1:  1 0.7224877 0.4729436 0.88773445 0.3081957 0.0379483
2:  2 0.7629343 0.9226372 0.06482454 0.7126673 0.4047996
3:  3 0.1423318 0.9317842 0.77045695 0.3122390 0.5333623
4:  4 0.9592109 0.8323915 0.30976919 0.3952811 0.1727833
5:  5 0.7556562 0.4359695 0.99086645 0.6474944 0.0738418", drop = 1L)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    • 2017-03-04
    相关资源
    最近更新 更多