在我需要使用来自数据帧的数据和来自其他数据帧的样本的情况下,我正在尝试提高速度。 首先,我需要从df_obs中抽取我想要的样本数量。 然后我需要根据我所在的月份(子命令)确定从哪里采样的子集。 然后我想从相应的示例数据帧中进行采样。 最后将它们放在一个新的数据框中。
下面的代码是Works,但是当我不得不重复这1000次时,它很慢。是否有更好的使用应用函数的替代方法?或者也许是一些data.table函数?
#Sample function to sample correct in case of only one value to sample from
resample <- function(x, ...) x[sample.int(length(x), ...)]
#Creating dummy data
no_pr_month <- sort(sample(67:120, 20))
df_obs <- data.frame(replicate(20,sample(0:5,1000,rep=TRUE)))
colnames(df_obs) <- no_pr_month
amount <- sample(50:50000,200)
month <- sample(no_pr_month,200, rep=TRUE)
df <- data.frame(month,amount)
df_sum <- data.frame(matrix(NA, ncol = 20, nrow=1000))
#The far too slow loop
for (k in 1:length(no_pr_month)){
a <- df_obs[,k]
df_sample <- subset(df, df$month == names(df_obs[k]))
df_out <- sapply(a, function(x) sum(resample(df_sample$amount, x,replace = TRUE)))
df_sum[,k] <- df_out
}
答案 0 :(得分:0)
注意:在创建数据之前,我插入了set.seed(000)
以获得一致的结果
即使使用data.table
软件包,最好以“整洁”的方式组织数据:基于行。
因此,我们首先将您的df_obs
数据集更改为长格式data.table。
library(data.table)
df_obs_long <- data.table(
month = as.integer(rep(names(df_obs), each = nrow(df_obs))),
obs_count = unlist(df_obs)
)
df_obs_long
# month obs_count
# 1: 69 4
# 2: 69 5
# 3: 69 1
# 4: 69 3
# 5: 69 0
# ---
# 19996: 116 4
# 19997: 116 1
# 19998: 116 2
# 19999: 116 3
# 20000: 116 5
接下来,我们将定义一个函数,该函数采用样本大小的向量和从中抽取样本的月份数。该函数将返回给定的每个尺寸的样本总和向量。
使df
成为data.table
并不会为编写代码节省太多,但可以减少运行时间。
setDT(df)
sample_and_sum_month <- function(sizes, month_number) {
choices <- df[month == month_number, amount]
vapply(
sizes,
FUN.VALUE = numeric(1),
FUN = function(s) {
sum(resample(choices, size = s, replace = TRUE))
}
)
}
sample_and_sum_month(1:3, 69)
# [1] 12729 55068 28605
最后,我们可以将这些总和添加为df_obs_long
中的新列。
df_obs_long[
,
sample_sum := sample_and_sum_month(obs_count, .BY[["month"]]),
by = "month"
]
df_obs_long
# month obs_count sample_sum
# 1: 69 4 82662
# 2: 69 5 160761
# 3: 69 1 5743
# 4: 69 3 108783
# 5: 69 0 0
# ---
# 19996: 116 4 56792
# 19997: 116 1 22570
# 19998: 116 2 35337
# 19999: 116 3 64734
# 20000: 116 5 69075