【发布时间】:2014-10-02 00:19:49
【问题描述】:
以下是我正在经历并坚持的一种情况的可重现示例(它是一个测试客户端我用来评估合并数据集用于我的论文研究)。
testData <- "https://github.com/abnova/test/blob/master/mergeTestData.zip?raw=true"
tmpFile <- tempfile()
tmpDir <- tempdir()
download.file(testData, tmpFile, method = 'curl',
extra = '-L', quiet = TRUE)
testFiles <- unzip(tmpFile, exdir = tmpDir)
# To enable desired merge option, uncomment corresponding line
#MERGE_OPTION <- "lapply_merge"
#MERGE_OPTION <- "lapply_merge2"
#MERGE_OPTION <- "reduce_merge"
#MERGE_OPTION <- "reduce_merge2"
#MERGE_OPTION <- "reshape"
#MERGE_OPTION <- "plyr"
#MERGE_OPTION <- "dplyr"
MERGE_OPTION <- "data.table"
#MERGE_OPTION <- "data.table2"
loadData <- function (dataFile) {
if (file.exists(dataFile)) {
data <- readRDS(dataFile)
}
else { # error() undefined - replaced for stop() for now
stop("Data file \'", dataFile, "\' not found! Run 'make' first.")
}
return (data)
}
loadDataSets <- function (dataDir) {
dataSets <- list()
dataFiles <- dir(dataDir, pattern='\\.rds$')
dataSets <- lapply(seq_along(dataFiles),
function(i) {
nameSplit <- strsplit(dataFiles[i], "\\.")
dataset <- nameSplit[[1]][1]
assign(dataset,
loadData(file.path(dataDir, dataFiles[i])))
return (get(dataset))
})
return (dataSets)
}
# load the datasets of transformed data
dataSets <- loadDataSets(tmpDir)
if (MERGE_OPTION == "lapply_merge") { # Option 1
flossData <- data.frame(dataSets[[1]][1])
# merge all loaded datasets by common column ("Project ID")
silent <- lapply(seq(2, length(dataSets)),
function(i) {merge(flossData, dataSets[[1]][i],
by = "Project ID",
all = TRUE)})
}
if (MERGE_OPTION == "lapply_merge2") { # Option 1
pids <- which(sapply(dataSets,
FUN=function(x) {'Project ID' %in% names(x)}))
flossData <- dataSets[[pids[1]]]
for (id in pids[2:length(pids)]) {
flossData <- merge(flossData, dataSets[[id]],
by='Project ID', all = TRUE)
}
}
if (MERGE_OPTION == "reduce_merge") { # Option 2
flossData <- Reduce(function(...)
merge(..., by.x = "row.names", by.y = "Project ID", all = TRUE),
dataSets)
}
# http://r.789695.n4.nabble.com/merge-multiple-data-frames-tt4331089.html#a4333772
if (MERGE_OPTION == "reduce_merge2") { # Option 2
mergeAll <- function(..., by = "Project ID", all = TRUE) {
dotArgs <- list(...)
dotNames <- lapply(dotArgs, names)
repNames <- Reduce(intersect, dotNames)
repNames <- repNames[repNames != by]
for(i in seq_along(dotArgs)){
wn <- which( (names(dotArgs[[i]]) %in% repNames) &
(names(dotArgs[[i]]) != by))
names(dotArgs[[i]])[wn] <- paste(names(dotArgs[[i]])[wn],
names(dotArgs)[[i]], sep = ".")
}
Reduce(function(x, y) merge(x, y, by = by, all = all), dotArgs)
}
flossData <- mergeAll(dataSets)
}
if (MERGE_OPTION == "reshape") { # Option 3
if (!suppressMessages(require(reshape))) install.packages('reshape')
library(reshape)
flossData <- reshape::merge_all(dataSets)
}
if (MERGE_OPTION == "plyr") { # Option 4
if (!suppressMessages(require(plyr))) install.packages('plyr')
library(plyr)
flossData <- plyr::join_all(dataSets)
}
if (MERGE_OPTION == "dplyr") { # Option 5
if (!suppressMessages(require(dplyr))) install.packages('dplyr')
library(dplyr)
flossData <- dataSets[[1]][1]
flossData <- lapply(dataSets[[1]][-1],
function(x) {dplyr::left_join(x, flossData)})
}
if (MERGE_OPTION == "data.table") { # Option 6
if (!suppressMessages(require(data.table)))
install.packages('data.table')
library(data.table)
flossData <- data.table(dataSets[[1]], key="Project ID")
for (id in 2:length(dataSets)) {
flossData <- merge(flossData, data.table(dataSets[[id]]),
by='Project ID', all.x = TRUE, all.y = FALSE)
}
}
# http://stackoverflow.com/a/17458887/2872891
if (MERGE_OPTION == "data.table2") { # Option 6
if (!suppressMessages(require(data.table)))
install.packages('data.table')
library(data.table)
DT <- data.table(dataSets[[1]], key="Project ID")
flossData <- lapply(dataSets[[1]][-1], function(x) DT[.(x)])
}
# Additional Transformations (see TODO above)
# convert presence of Repo URL to integer
flossData[["Repo URL"]] <- as.integer(flossData[["Repo URL"]] != "")
# convert License Restrictiveness' factor levels to integers
#flossData[["License Restrictiveness"]] <-
# as.integer(flossData[["License Restrictiveness"]])
# convert User Community Size from character to integer
flossData[["User Community Size"]] <-
as.integer(flossData[["User Community Size"]])
# remove NAs
#flossData <- flossData[complete.cases(flossData[,3]),]
rowsNA <- apply(flossData, 1, function(x) {any(is.na(x))})
flossData <- flossData[!rowsNA,]
print(str(flossData))
错误信息如下:
Starting bmerge ...done in 0.001 secs
Starting bmerge ...done in 0.002 secs
Error in vecseq(f__, len__, if (allow.cartesian) NULL else as.integer(max(nrow(x), :
加入结果为 121229 行;超过 100000 = 最大(nrow(x),nrow(i))。检查 i 中的重复键值,每个 它一遍又一遍地加入 x 中的同一组。如果没问题的话 尝试包括
j并删除by(by-without-by) 以便 j 运行 每个组避免大分配。如果你确定你想 继续,使用 allow.cartesian=TRUE 重新运行。否则,请搜索 FAQ、Wiki、Stack Overflow 和 datatable-help 中的此错误消息 寻求建议。
当前问题与启用的 data.table 选项有关,但是,由于它是同一个包,我也希望能提供关于下一个选项的建议,它使用 alternative data.table merging 的 syntax (尽管我觉得它太混乱了,但为了知识的完整性)。提前谢谢!
【问题讨论】:
-
忘了说:我很好奇为什么错误信息列出了 121229 行,而我的 base 数据框(通过
all.x = TRUE, all.y = FALSE指定)用于 left join 正好有 100000 行。 -
从错误信息中你有什么不明白的地方?
-
@Arun:正如我在之前的评论中提到的,我不明白 left join 合并导致的数据框中的行数如何更高比 base(左)数据框中的行数。
标签: r merge dataframe data.table