【问题标题】:Comparing a vector against each element of another vector将一个向量与另一个向量的每个元素进行比较
【发布时间】:2021-02-12 21:41:57
【问题描述】:

我正在尝试跟踪事件随时间的累积,例如过去一年 COVID 病例和死亡总数的图表。我的起始数据是个人(行)列表,列中包含每个事件的日期。一个简化的例子是:

library(data.table)
#   Set up 20 subjects and # of days at which each of 3 events happen
(events<-data.table(Subject=1:20, Event1=100*runif(20), Event2=200*runif(20), Event3=500*runif(20)))
(accrual<-data.table(days=10*1:10))  
# Col. 1 has timepoints at which I want to count events occurring by that date

我的快速计数方法是将事件(一列)的整个日期列表与单个日期进行比较,例如第 50 天:

> events[Event1 < 70, length(Subject)]
[1] 12

我一直在尝试将 3 列中的每一列与列表中的每个日期进行迭代比较,以构建一个可用于绘制应计项目的表格(例如,请参见问题结尾)。任何时候我尝试将其作为向量操作(data.table,应用函数),结果只是一个计数,而不是每个日期的计数向量

> events[Event1 < accrual$days, length(Subject)]
[1] 11
> events[Event1 < accrual[,days], length(Subject)]
[1] 11
> sum(events$Event1 < accrual$days[1:10])
[1] 11

这似乎是成对比较事件和日期的向量,这是广告的行为。我真正想要的是针对日期的第一个元素,然后是日期的第二个元素等对整个列进行评估。多年来使用 data.table 和 dpylr,我认为应该有一种更优雅的方式来做到这一点而不是在我走的时候循环和计数。以下代码有效,但我觉得我缺少一个更简单、更优雅的解决方案。

> # Ugly, manual way to count events for each date.
> t2<-NULL
> for(i in accrual$days) {
+   t1<-sum( events[, Event1] < i )
+   t2<-c(t2, t1)
+ }
> accrual[,Events1:=t2]
> t2<-NULL
> for(i in accrual$days) {
+   t1<-sum( events[, Event2] < i )
+   t2<-c(t2, t1)
+ }
> accrual[,Events2:=t2]
> t2<-NULL
> for(i in accrual$days) {
+   t1<-sum( events[, Event3] < i )
+   t2<-c(t2, t1)
+ }
> accrual[,Events3:=t2]
> accrual
    days Events1 Events2 Events3
 1:   10       2       1       0
 2:   20       7       2       0
 3:   30       9       2       0
 4:   40      10       4       0
 5:   50      11       5       1
 6:   60      11       6       1
 7:   70      12       6       1
 8:   80      16       6       1
 9:   90      18       8       3
10:  100      20       8       3

感谢您的建议。

【问题讨论】:

    标签: r vector data.table comparison counting


    【解决方案1】:

    这里有一个data.table 选项可能会有所帮助

    > accrual[, as.list(colSums(events[, -c("Subject")] <= days)), days]
        days Event1 Event2 Event3
     1:   10      4      2      0
     2:   20      6      3      0
     3:   30     10      5      1
     4:   40     12      7      3
     5:   50     13      7      3
     6:   60     15      8      4
     7:   70     16      8      4
     8:   80     19      9      4
     9:   90     20     11      4
    10:  100     20     13      4
    

    【讨论】:

    • 如果有人遇到类似的情况,我这里的示例是从我的实际项目中简化的,该项目将数据作为日期而不是数字。当我在那里使用 ThomasIsCoding 的解决方案时,应用不等式时出现错误:```` is.data.frame(x) 中的错误:'list' 对象不能被强制输入'integer' 另外:警告消息:In is .data.frame(x) :````。
    • @KJG 你能dput 一个虚拟数据,就像你的实际项目数据和日期吗?
    【解决方案2】:

    这是一个使用非等连接的选项:

    cols <- paste0("Event", 1:3)
    for (x in cols) {
        accrual[, (x) := events[.SD, on=paste0(x,"<days"), by=.EACHI, .N]$N]
    }
    accrual[]
    

    输出:

              days Event1 Event2 Event3
     1: 1970-01-11      1      1      0
     2: 1970-01-21      2      1      1
     3: 1970-01-31      5      3      1
     4: 1970-02-10      8      4      2
     5: 1970-02-20      9      5      3
     6: 1970-03-02     10      6      3
     7: 1970-03-12     13      7      3
     8: 1970-03-22     15      9      3
     9: 1970-04-01     17      9      3
    10: 1970-04-11     20     11      3
    

    数据:

    library(data.table)
    set.seed(0L)
    events <- data.table(Subject=1:20, Event1=100*runif(20), Event2=200*runif(20), Event3=500*runif(20))
    cols <- paste0("Event", 1:3)
    events[, (cols) := lapply(.SD, as.IDate), .SDcols=cols]
    accrual <- data.table(days=as.IDate(10*1:10))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-25
      • 2017-09-27
      相关资源
      最近更新 更多