将许多 CSV 合并到不同的数据框中

Posted

技术标签:

【中文标题】将许多 CSV 合并到不同的数据框中【英文标题】:Merging many CSVs into different data frames 【发布时间】:2015-09-16 17:30:54 【问题描述】:

我有很多 CSV,每个对应一天的数据,存储如下:

Day1.csv:

ID, height, weight, color
a1, 3, 45, blue
a2, 3, 44, green
a3, 4, 48, blue

第 2 天.csv:

ID, height, weight, color
a1, 4, 47, green
a2, 4, 44, green
a3, 5, 49, yellow

我想为每个特征(即身高、体重等)制作一个单独的数据框,其中包含来自每个 csv 的信息。每个特征的输出如下所示:

高度.df:

ID, Day1, Day2
a1, 3, 4
a2, 3, 4
a3, 3, 5

我曾尝试使用merge(),但这要求我一次只输入两列。我也不确定如何使用文件名来标记列。

【问题讨论】:

你卡在问题的哪一部分?读取多个 CSV 文件?读入后合并文件中的数据? 在读入文件后合并文件中的数据。如果我不清楚,请见谅 【参考方案1】:

这似乎适用于两个数据框。

file_names <- list.files('C:/mydirectory/mycsvs', full.names = T)
file_list <- lapply(file_names, read.csv, stringsAsFactors = F)

所以把你的 csvs 放在一个目录中,把它们读入一个列表。

library(dplyr)

new_dataframes = list()
for(i in 2:ncol(dataframes[[1]]))
  new_list <- list()
  for(j in 1:length(file_list))
    new_list[[j]] <- file_list[[j]][, c(1, i)]
  
  joined_df <- new_list[[1]]
  for(j in 2:length(new_list))
    joined_df <- inner_join(joined_df, new_list[[j]], by = 'ID')
  
  for(j in 2:ncol(joined_df))
    colnames(joined_df)[j] <- paste0('day ', j - 1)
  
  feature_name <- colnames(new_list[[1]])[2]
  new_dataframes[[feature_name]] <- joined_df


new_dataframes

$height
  ID day 1 day 2
1 a1     3     4
2 a2     3     4
3 a3     4     5

$weight
  ID day 1 day 2
1 a1    45    47
2 a2    44    44
3 a3    48    49

$color
  ID day 1  day 2
1 a1  blue  green
2 a2 green  green
3 a3  blue yellow

这假设您有连续的天数(例如,您从第 1 天到第 n 天没有丢失的天数。如果不是这种情况,那么从文件标题中提取日期并不难,假设它在标题中。这还假设每个数据帧在列数/列顺序方面或多或少相同。如果不是这种情况,这将行不通。它还会执行inner_join,因此您只会获取记录具有匹配的 ID。

如果有人有摆脱这些循环的想法,我很想听听,尤其是对于那个 join 步骤。根据数据的大小,这可能会变得相对较慢。

无论如何,您最终会得到一个数据框列表,其中列表元素的名称就是特征。根据您拥有的数据量,此列表可能会变得非常大。

【讨论】:

【参考方案2】:

我会考虑将所有数据放入一个列表中,然后rbind将数据放在一起(如果列属于相同类型)。

例子:

## Assume you have read in files and saved them as `data.frame`s named
##  "day1", "day2", and so on....
temp <- mget(ls(pattern = "day\\d+"))
long <- do.call(rbind, lapply(names(temp), function(x) cbind(Day = x, temp[[x]])))

从那里,您可以很容易地进行转换。例如,将整个数据集变成一个“宽”数据集:

reshape(long, direction = "wide", idvar = "ID", timevar = "Day")
#   ID height.day1 weight.day1 color.day1 height.day2 weight.day2 color.day2
# 1 a1           3          45       blue           4          47      green
# 2 a2           3          44      green           4          44      green
# 3 a3           4          48       blue           5          49     yellow

或者,只是一个特定的变量:

library(data.table)
dcast.data.table(as.data.table(long), ID ~ Day, value.var = "height")
#    ID day1 day2
# 1: a1    3    4
# 2: a2    3    4
# 3: a3    4    5

【讨论】:

【参考方案3】:

如果您真的想制作单独的数据框,可以使用以下方法:

Day1.csv <- read.table(header=T, sep=",", text="
ID, height, weight, color
a1, 3, 45, blue
a2, 3, 44, green
a3, 4, 48, blue")

Day2.csv <- read.table(header=T, sep=",", text="
ID, height, weight, color
a1, 4, 47, green
a2, 4, 44, green
a3, 5, 49, yellow")

library(tidyr)
l <- mget(ls(pattern = "Day\\d+\\.csv"))
df <- do.call(rbind, lapply(seq(l), function(x) transform(l[[x]], Day = paste0("Day", gsub("\\D", "", names(l)[x])))))
df <- gather(df, variable, value, -ID, -Day)
list2env(
  setNames(lapply(levels(df$variable), function(x)  
  spread(df[df$variable == x, -which(names(df) == "variable")], Day, value, fill = 0)
), paste0(levels(df$variable), ".df")), globalenv())

weight.df
# ID Day1 Day2
# 1 a1   45   47
# 2 a2   44   44
# 3 a3   48   49

height.df
# ID Day1 Day2
# 1 a1    3    4
# 2 a2    3    4
# 3 a3    4    5

color.df
# ID   Day1    Day2
# 1 a1   blue   green
# 2 a2  green   green
# 3 a3   blue  yellow

【讨论】:

以上是关于将许多 CSV 合并到不同的数据框中的主要内容,如果未能解决你的问题,请参考以下文章

如何将不同 .csv 文件中的所有数据合并到一个表中?

将具有不同架构(列)的多个文件 (.csv) 合并/合并为单个文件 .csv - Azure 数据工厂

将来自不同文件夹的多个 csv 文件(相似名称)合并到一个 csv 中并逐行绑定它们 [关闭]

将重复记录合并到 pyspark 数据框中的单个记录中

基于文本字段在 Pandas Dataframes 中合并 CSV 文件

合并具有不同列名但定义相同的多个CSV