我有这个R脚本:
rm(list = ls())
library(tidyr)
suppressWarnings(library(dplyr))
outFile = "zFinal.lua"
cat("\014\n")
cat(file = outFile, sep = "")
filea <- read.csv("csva.csv", strip.white = TRUE)
fileb <- read.csv("csvb.csv", strip.white = TRUE, sep = ";", header=FALSE)
df <-
merge(filea, fileb, by.x = c(3), by.y = c(1)) %>%
subset(select = c(1, 3, 6, 2)) %>%
arrange(ColA, ColB, V2) %>%
group_by(ColA) %>%
mutate(V2 = paste0('"', V2, "#", ColB, '"')) %>%
summarise(ID = paste(V2, collapse = ", ", sep=";")) %>%
mutate(ID = paste0('["', ColA, '"] = {', ID, '},')) %>%
mutate(ID = paste0('\t\t', ID))
df <- df[c("ID")]
cat("\n\tmyTable = {\n", file = outFile, append = TRUE, sep = "\n")
write.table(df, append = TRUE, file = outFile, sep = ",", quote = FALSE, row.names = FALSE, col.names = FALSE)
cat("\n\t}", file = outFile, append = TRUE, sep = "\n")
# Done
cat("\nDONE.", sep = "\n")
如您所见,此脚本将打开csva.csv和csvb.csv。
这是csva.csv:
ID,ColA,ColB,ColC,ColD
2,3,100,1,1
3,7,300,1,1
5,7,200,1,1
11,22,900,1,1
14,27,500,1,1
16,30,400,1,1
20,36,900,1,1
23,39,800,1,1
24,42,700,1,1
29,49,800,1,1
45,3,200,1,1
这是csvb.csv:
100;file1
200;file2
300;file3
400;file4
这是我的脚本和csv文件生成的输出文件:
myTable = {
["3"] = {"file1#100", "file2#200"},
["7"] = {"file2#200", "file3#300"},
["30"] = {"file4#400"},
}
此输出文件正是我想要的。完美。
这就是脚本的作用。我不确定我能否很好地解释这一点,因此,如果我做的不好,请跳过本节。
对于csva.csv中的每一行,如果ColC(csva)包含列1(csvb)中包含的数字,则输出文件应包含这样的行:
["3"] = {"file1#100", "file2#200"},
因此,在上面的示例中,ColA(csva)的第一行包含数字3,该行的colB为100。在csvb中,列1包含100,列2包含file1#100。
因为csva在ColA(最后一行)中包含另一个数字3,所以也会对其进行处理并输出到同一行。
好,所以我的脚本确实运行得很好,并产生完美的输出。问题是运行时间太长。我的问题中的csva和csvb只有几行,因此输出是即时的。
但是,我必须在现实世界中使用的数据-csva超过300,000行,而csvb超过900,000行。因此,脚本需要很长时间才能运行(太长了才能使其可行)。它确实可以很好地工作,但是运行时间太长。
通过逐渐注释掉行,似乎减速是由于变异和总结。如果没有这些行,脚本将在大约30秒内运行。但是通过变异和总结,它需要几个小时。
我对R不太了解,如何通过改善语法或提供更快的替代方法来进行变异和汇总来使脚本运行得更快?
您可以尝试将表格加载为data.table。通常,data.tables的操作比data.frames更快]
library(data.table) filea <- fread("csva.csv")
在使用mutate函数之前,只需检查它是否仍然是data.table(只需打印它,就会发现与data.frame有明显的区别)。
这是一种非常贴近您的方法。真正的区别在于,应尽快从对象上放下行和列,以减少行进中的负担。