我有一个包含 12,626,756 行的 csv 文件,我需要将其拆分为更小的文件,以便同事可以在 Excel 中打开它们。我想创建一个循环,将文件拆分为适合 Excel 行限制的文件,并将它们导出为 CSV 文件,直到到达末尾(它应该生成 13 个文件)
#STEP 1: load data
data <- read.csv(".../Desktop/Data/file.csv", header = TRUE)
#STEP 2: count rows
totalrows <- nrow(data)
#STEP 3: determine how many splits you need
excelrowlimit <- 1048576 - 5
filesrequired <- ceiling(totalrows/ excelrowlimit)
例如:
csvfile 1 should contain rows 1:1048571
csvfile 2 should contain rows 1048572:2097143
csvfile 3 should contain rows 2097144:3145715
csvfile 4 should contain rows 3145716:4194287
... and so on
如何编写一个循环语句,(1) 按所需文件数量进行分割,(2) 为每个 csv 导出提供不同的文件名?
这是扩展我上面评论的解决方案。这应该比任何其他解决方案具有更小的内存需求,因为它不需要复制全部或部分原始数据帧。
library(tidyverse)
rowCount <- 1048571
data %>%
mutate(Group = ceiling((row_number()) / rowCount)) %>%
group_by(Group) %>%
group_walk(
function(.x, .y) {
write.csv(.x, file = paste0("file", .y$Group, ".csv"))
}
)
这是如何实现此目的的示例,您可以使用
split_at
设置所需的文件大小。
在最后一部分中,您当然可以根据需要更改 write_csv 参数,例如设置路径、分隔符等
library(tidyverse)
split_at <- 5
data.frame(x = 1:19) %>%
mutate(group = (row_number() - 1) %/% !! split_at) %>%
group_split(group) %>%
map(.f = ~write_csv(.x, file = paste0('file ', unique(.x$group), '.csv')))
我假设每500行分割数据。您可以将一列变异为标签组。然后放入for循环根据该列写出csv。
#STEP 1: load data
data <- read.csv(".../Desktop/Data/file.csv", header = TRUE)
# mutate a column to lable the group
data <- data %>% mutate(Group = ceiling(1:nrow(.)/500))
# write out csv by group
for(i in unique(data$Group)){
data %>% filter(Group == i) %>% select(-Group) %>%
write.csv(paste0("/your/path/",i,".csv"))
}
这将确定 csv 的长度,然后一次只读取所需的块以进行写入。这是为了潜在地避免较大文件/内存不足的内存问题。每个文件都将具有相同的标头,并在相同的文件名后附加一个数字。 Excel 行限制可能略高于 1m,因此使用它作为行大小
inputFile <- 'yourFile.csv'
library(data.table)
rowsDone <- 0
counter <- 0
# number of rows per file
chunkSize = 1000000
totalRows <- nrow(fread(inputFile, header = F, select = 1L))
header <- names(fread(inputFile, nrows = 0))
while (rowsDone < totalRows)
{
chunkSize <- min(totalRows - rowsDone, chunkSize)
print(paste0('writing rows: ', rowsDone + 1, ' to ', rowsDone + chunkSize))
tempDF <- fread(inputFile, nrows = chunkSize, skip = rowsDone, header = F) # ignores header
names(tempDF) <- header
if (counter == 0) tempDF <- tempDF[-1]
rowsDone <- rowsDone + chunkSize
counter <- counter + 1
fwrite(tempDF, paste0(sub('.csv', '', inputFile), '_', counter, '.csv'))
}