将一个向量与另一个向量的每个元素进行比较
Comparing a vector against each element of another vector
我正在尝试跟踪事件随时间的累积,例如过去一年 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 列中的每一列与列表中的每个日期进行迭代比较,以构建一个 table 我可以用来绘制应计利润的图表(例如,请参见问题结尾)。任何时候我尝试将此作为向量运算(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
感谢您的建议。
这里有一个 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
这是一个使用非等值连接的选项:
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))
我正在尝试跟踪事件随时间的累积,例如过去一年 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 列中的每一列与列表中的每个日期进行迭代比较,以构建一个 table 我可以用来绘制应计利润的图表(例如,请参见问题结尾)。任何时候我尝试将此作为向量运算(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
感谢您的建议。
这里有一个 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
这是一个使用非等值连接的选项:
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))