我有一个数据集,我正试图用它在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)