我如何简化这个代码(r)?在这个代码中,我使用原始数据集的信息来创建新的数据集



我有一个数据集,我正试图用它在R中生成一个不同的数据集。数据集有很多列;但是用于生成新数据集的三个相关列是"0";Reach"结果";,以及";DV";。到达和结果是数字。DV是二进制的,有0和1。在原始数据集中,所有行的DV=0。

对于原始数据集的每一行;Reach";并复制该行";达到";次数。然后对于这组新的行;结果";新行的数目(来自原始行(。

例如,在原始数据集的第33行中:Reach=1004,Results=45,DV=0。新的数据集应该将行33复制1004次,因为其中45个新行DV应该从0更改为1。

我为任务编写的代码有效。。。但由于文件太大,运行需要10多个小时。关于如何简化此代码以便更快地处理的任何想法

empty_new.video <- new.video[FALSE,]
for(i in 1:nrow(new.video)){
n.times <- new.video[i,'Reach'] #determine number of times to repeat rows
if (n.times > 0){
for (j in 1:n.times){
empty_new.video[nrow(empty_new.video) + 1 , ] <- new.video[i,]
}
}
dv.times <- new.video[i,'Results'] #creating dependent variable 
if (dv.times>0){
for (k in 1:dv.times){
empty_new.video[nrow(empty_new.video) - n.times + k,'DV'] <- 1
}
}
}

您可以定义一个简单的函数来对一行执行此操作,并检查结果

dd <- data.frame(Reach = c(5, 3), Results = c(4, 1), DV = c(0, 0))
#   Reach Results DV
# 1     5       4  0
# 2     3       1  0
f <- function(data) {
nr <- data$Reach
nd <- data$Results
data <- data[rep_len(1L, nr), ]
data$DV <- rep(0:1, c(nr - nd, nd))
rownames(data) <- NULL
data
}
f(dd[1, ])

然后每行循环

res <- lapply(split(dd, rownames(dd)), f)
do.call('rbind', res)
#     Reach Results DV
# 1.1     5       4  0
# 1.2     5       4  1
# 1.3     5       4  1
# 1.4     5       4  1
# 1.5     5       4  1
# 2.1     3       1  0
# 2.2     3       1  0
# 2.3     3       1  1

但实际上,您所要做的只是为DV创建一个行索引和0/1值的向量,您可以使用rep来实现这一点

ii <- rep(1:nrow(dd), dd$Reach)
jj <- c(t(cbind(dd$Reach - dd$Results, dd$Results)))
dv <- rep(rep(0:1, nrow(dd)), jj)
within(dd[ii, ], {
DV <- dv
})
#     Reach Results DV
# 1       5       4  0
# 1.1     5       4  1
# 1.2     5       4  1
# 1.3     5       4  1
# 1.4     5       4  1
# 2       3       1  0
# 2.1     3       1  0
# 2.2     3       1  1

避免循环中的对象增长。考虑Map(mapply的包装器(元素遍历所有原始数据集的列,以构建一个数据帧列表,最终在末尾连接一次

build_rows <- function(reach, results) {
# DATA FRAME TO REPLICATE REACH BY ITS LENGTH
df <- data.frame(id = reach, reach = 1:reach, dv = 0)
# RANDOMLY ASSIGN N ROWS TO 1 (N=RESULTS)  
df$dv[sample(1:nrow(df), results),] = 1 
# ASSIGN FIRST N ROWS TO 1 (N=RESULTS)
df$dv[1:results,] = 1 
return(df)
}
df_list <- Map(build_rows, original_data$Reach, original_data$Results)
final_df <- do.call(rbind, df_list)

相关内容

最新更新