使用合并功能合并多个 CSV 文件,同时保留文件名信息

问题描述 投票:0回答:3

提出了几个与我类似的问题并得到了回答,但是他们都使用了

pd.concat
,而我想使用
merge
或可以给我类似结果的东西。

我想将多个 CSV 文件合并到一个主 df 中。我的所有 CSV 文件都有相同的两列(“gene”和“log2foldchange”)。

我的 CSV 文件都类似于以下内容:

基因 log2foldchange
基因1 0.03
基因2 0.02
基因3 0.01
基因4 0.05

每个 CSV 文件:

  • 具有完全相同的 4 个基因和列名称
  • 有一个不同的名字(显然)

我想将 CSV 文件的名称合并为存储 log2foldchange 值的列名称,以便我知道数据来自哪里。我希望我的最终 master df 看起来像下面这样:

第一个 CSV_文件的名称 第二个 CSV_文件的名称 第 3 个 CSV 文件的名称 第 4 个 CSV_文件的名称
基因1 0.08 0.09 0.07 0.01
基因2 0.07 0.03 0.06 0.001
基因3 0.08 0.06 0.05 0.2
基因4 0.09 0.02 0.03 0.011

我能够成功地使用

pd.concat
将所有 CSV 文件合并到一个主 df 中,但是,我最终 df 的结构是所有 CSV 文件都堆叠在一起。这种结构对于我想做的分析类型没有意义。我想使用
merge
,但我遇到的问题是它需要 two 对象,我不知道如何解决这个问题。

此外,我只能将文件名作为其自己的单独列,而不是像我希望的那样作为 log2fold 更改的列名。

这是我使用 pd.concat 的代码:

source_files = sorted(Path('path/to/my/files').glob('*.csv'))

dataframes = []
for file in source_files:
    df = pd.read_csv(file) 
    df['source'] = file.name
    dataframes.append(df)

df_all = pd.concat(dataframes)
display(df_all)

这会产生如下所示的 df:

基因 log2foldchange 来源
基因1 0.03 第一个 CSV 文件
基因2 0.02 第一个 CSV 文件
基因3 0.01 第一个 CSV 文件
基因4 0.04 第一个 CSV 文件
基因1 0.05 第二个 CSV 文件
基因2 0.06 第二个 CSV 文件

等等...

这是我使用 pd.merge 的代码,它会导致错误,因为只给出了一个对象:

path = 'path/to/my/files'
all_files = glob.glob(os.path.join(path, "*.csv")) #make list of file paths 

#initialize empty data frame 
li = []

for filename in all_files:
    df = pd.read_csv(filename, index_col=None, header=0)
    li.append(df)

frame = pd.merge(li, axis=0, ignore_index=True)
display(frame)
python pandas merge concatenation
3个回答
1
投票

编辑:根据评论进行调整

这行得通吗?

from functools import reduce

list_of_dfs = []

for file in all_files:
    df = pd.read_csv(file, header=0, sep=",") #Change sep to whatever separates your data
    df = df.loc[:, ['gene', 'log2foldchange']] #Subset out only the two columns you want
    file_name = os.path.splitext(os.path.basename(file))[0] #Get filename without extension
    df = df.rename(columns={'log2foldchange': file_name}) #Rename log2fold column with file name
    list_of_dfs.append(df) #Add df to list of dfs

df_merged = reduce(lambda left,right: pd.merge(left,right,on='gene',how='outer'), list_of_dfs)

0
投票

比接受的答案更短、更高效的代码,尤其是对于大文件数。

这不是一个

.concat
问题。将文件源作为新列进行跟踪是一个好主意。但您在这里想要的是直接重命名保存数据的列。

您最终会这样做,所以为什么不跳过额外的临时列呢?

考虑一下:

# 1. This is your pre-processing. Shape the unit dataframes for aggregation.
def csv_to_df(file):
    '''Convert file path to unit dataframe'''
    df = pd.read_csv(file) 
    return df.rename(columns={'log2foldchange' : file.name})

# 2. concat works naturally
df_all = pd.concat( [csv_to_df(file) for file in source_files], axis=1)

您寻求的内容保持在 4 行中,并且没有

for
循环,因为对于大文件数,建议使用数据帧的列表理解,而不是用
list.append
结束每次迭代的循环。


0
投票

使用以下代码在 python 中合并两个 csv 文件。它创建一个 DataFrame 列表,每个 DataFrame 包含“

gene
”列和以文件命名的 log2foldchange 列。然后,它根据“
DataFrames
”列合并这些
gene

import pandas as pd
from pathlib import Path

source_files = sorted(Path('path/to/my/files').glob('*.csv'))

dataframes = []
for file in source_files:
    df = pd.read_csv(file)
    # Create a new column with log2foldchange values named after the file
    df[file.stem] = df['log2foldchange']
    dataframes.append(df[['gene', file.stem]])

# Merge DataFrames on the 'gene' column
df_all = dataframes[0]  # Initialize with the first DataFrame
for df in dataframes[1:]:
    df_all = pd.merge(df_all, df, on='gene')

# You can set 'gene' as the index
df_all.set_index('gene', inplace=True)

display(df_all)
© www.soinside.com 2019 - 2024. All rights reserved.