【问题标题】:Merging dataframes by file name按文件名合并数据框
【发布时间】:2016-12-20 19:55:13
【问题描述】:

我有多个具有以下命名约定的文件。

ENCSR000EQO_0_0.txt
ENCSR000DIA_0_0.txt
ENCSR000DIA_1_1.txt
ENCSR000DIA_2_1.txt
ENCSR000DIM_0_0.txt
ENCSR000DIM_1_1.txt
ENCSR000AIB_0_0.txt
ENCSR000AIB_1_1.txt
ENCSR000AIB_2_1.txt
ENCSR000AIB_3_1.txt

我想根据文件名使用 pandas 将它们合并为数据帧,因此我将得到 4 个结果数据帧。然后对于这 4 个中的每一个,我想按基因(GeneName)列进行分组。因为同一个基因会出现多次。

它们都以相同的顺序具有相同的列。我可以一次将所有 10 个合并在一起,但我不知道如何按名称合并。

path = '/renamed/'

print os.listdir(path)

df_merge = None
for fname in os.listdir(path):
    if fname.endswith('.txt'):
        df = pd.read_csv(path + fname, sep='\t', header=0)
        df.columns = ['ID ', 'Chr', 'Start', 'End', 'Strand', 'Peak Score', 'Focus Ratio/Region Size', 
                     'Ann', 'DetAnn', 'Distance', 'PromoterID', 'EID', 
                     'Unigene', 'Refseq', 'Ensembl', 'GeneName', 'GeneAlias', 
                     'GeneDescription', 'GeneType']
        df = df.groupby('GeneName').agg(np.mean)
        print df

感谢您的任何意见。

【问题讨论】:

  • 我想你想要一个叫做join的东西。查找pd.merge
  • 也许this post 会有所帮助。

标签: pandas merge


【解决方案1】:

我会做更多类似的事情,您可以使用glob 来获取文件名,检查每个文件名,然后对连接的结果进行分组。

import glob
path = 'renamed'

df_merge = None
for fid in ('EQO', 'DIA', 'DIM', 'AIB'):
    df_ = pd.DataFrame()
    for fname in glob.glob(os.path.join(path, '*.txt')):
        if fid in fname:
            df = pd.read_csv(fname, sep='\t', header=0)
            df.columns = ['ID ', 'Chr', 'Start', 'End', 'Strand', 'Peak Score', 'Focus Ratio/Region Size', 
                         'Ann', 'DetAnn', 'Distance', 'PromoterID', 'EID', 
                         'Unigene', 'Refseq', 'Ensembl', 'GeneName', 'GeneAlias', 
                         'GeneDescription', 'GeneType']
            df_ = pd.concat((df_, df))
    df_ = df_.groupby('GeneName').agg(np.mean)
    print df_

编辑:扩展答案以更加自动化。

根据您的文件名,您可能可以按如下方式识别它们:

import numpy as np
files = glob.glob(os.path.join(path, '*.txt'))
fids = np.unique([file.split('_')[0] for file in files])

将它们放在一起更新的代码将是这样的:

import glob
import numpy as np
path = 'renamed'

files = glob.glob(os.path.join(path, '*.txt'))
fids = np.unique([file.split('_')[0] for file in files])

df_merge = None
for fid in fids:
    df_ = pd.DataFrame()
    for fname in files:
        if fid in fname:
            df = pd.read_csv(fname, sep='\t', header=0)
            df.columns = ['ID ', 'Chr', 'Start', 'End', 'Strand', 'Peak Score', 'Focus Ratio/Region Size', 
                         'Ann', 'DetAnn', 'Distance', 'PromoterID', 'EID', 
                         'Unigene', 'Refseq', 'Ensembl', 'GeneName', 'GeneAlias', 
                         'GeneDescription', 'GeneType']
            df_ = pd.concat((df_, df))
    df_ = df_.groupby('GeneName').agg(np.mean)
    print df_

【讨论】:

  • 我不熟悉 glob。这似乎是一个有趣的可能性,但在这种情况下,我实际上有 100000 个文件和很多文件名变化。
  • Glob 仍然很有帮助,它是标准库的一部分。请参阅我的扩展答案。
  • 为了提高性能,将所有 DF 存储在一个列表中并将调用 concat 推迟到最后通常是有益的。
  • 确实效果很好。特别是性能方面。已经完成了!我很惊讶。谢谢。
【解决方案2】:

尝试将文件名添加为列,将所有 df 附加到列表中并将它们连接起来,然后分组:

df_merge = []
for fname in os.listdir(path):
if fname.endswith('.txt'):
    df = pd.read_csv(path + fname, sep='\t', header=0)
    df.columns = ['ID ', 'Chr', 'Start', 'End', 'Strand', 'Peak     Score', 'Focus Ratio/Region Size', 
                 'Ann', 'DetAnn', 'Distance', 'PromoterID', 'EID', 
                 'Unigene', 'Refseq', 'Ensembl', 'GeneName', 'GeneAlias', 
                 'GeneDescription', 'GeneType']
    df['fname'] = [fname.split('_')[0] for x in df.index] #just to multiple by length 
    df_merge.append(df)

df_all = pd.concat(df_merge)

for fn in set(df_all['fname'].values):    
    print df_all[df_all['fname']==fn].groupby('GeneName').agg(np.mean)

【讨论】:

  • 这是一个绝妙的解决方案。为什么我从来没想过?呵呵,不过我的电脑占了很多。
猜你喜欢
  • 2014-05-02
  • 2018-01-29
  • 2015-11-09
  • 1970-01-01
  • 2021-03-31
  • 2021-07-06
  • 1970-01-01
  • 2018-11-29
  • 2018-03-09
相关资源
最近更新 更多