我如何简化这段代码 (r),我在其中使用原始数据集中的信息来创建新数据集?
How can I simplify this code (r) in which I am using information from an original data set to create a new dataset?
我有一个数据集,我试图用它在 R 中生成不同的数据集。数据集有很多列;但是生成新数据集的三个相关列是“Reach”、“Results”和“DV”。达到和结果是数字。 DV 是具有 0 和 1 的二进制。在原始数据集中,所有行的 DV = 0.
对于原始数据集的每一行,我尝试取一个变量“Reach”并复制该行“reach”次数。
然后对于这组新行,我想将新行的“结果”编号(来自原始行)的 DV 从 0 更改为 1。
例如,在原始数据集的第 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
}
}
}
避免在循环中增加对象。考虑 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)
您可以定义一个简单的函数,为一行执行此操作并检查结果,而不是一次执行所有操作的循环
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
我有一个数据集,我试图用它在 R 中生成不同的数据集。数据集有很多列;但是生成新数据集的三个相关列是“Reach”、“Results”和“DV”。达到和结果是数字。 DV 是具有 0 和 1 的二进制。在原始数据集中,所有行的 DV = 0.
对于原始数据集的每一行,我尝试取一个变量“Reach”并复制该行“reach”次数。 然后对于这组新行,我想将新行的“结果”编号(来自原始行)的 DV 从 0 更改为 1。
例如,在原始数据集的第 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
}
}
}
避免在循环中增加对象。考虑 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)
您可以定义一个简单的函数,为一行执行此操作并检查结果,而不是一次执行所有操作的循环
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