将文件合并到 python 中的 multiIndex 数据帧,最后导出到 txt

Combining files into multiIndex dataframe in python and finally export to txt

我有几个文件都具有相同的第一列 (X) 和相同的列名 (XBC) , 但第二列和第三列是不同的值。

X  | B | C
-----------
a    0   2
b    4   9
...
z    3   0

我想将所有这些表组合成一个大数据框,但每个部分都可以通过自己的索引访问,例如基于文件名。例如。 df['f1']['B'] 将是 [0, 4..., 3]。最终结果将如下所示。

   | f1 | f1 | f2 | f2 
X  | B  | C  | B  | C
-----------------------
a    0    2    3    2
b    4    9    1    2
...        
z    3    0    9    8

这是我目前的代码

import pandas as pd
import numpy as np
import regex as re

dir = 'directory'
path = os.path.abspath(os.path.join(os.getcwd(), dir))
# List all files in folder
filenames = [name for name in os.listdir(path) if re.match(".*\.txt$", name)]

r_coln = re.compile(r"\.txt$")

frames = []

for i in range(len(filenames)):
    filename = filenames[i]
    coln = r_coln.sub("", filename)
    if (i == 0):
        # Subtract the first column which is identical for all frames
        first_frame =  pd.read_csv(os.path.join(path, filename), usecols=[0], sep="\t", names=[''], header=None)
        frames.append(first_frame)

    # Get frame with a new header
    frames.append(pd.read_csv(os.path.join(path, filename), usecols=[1, 2], sep="\t", names=[coln, ''], header=None))

# Combine all frames
df = pd.concat(frames, axis=1)

这是因为生成的数据框确实看起来像我上面发布的示例,但每个文件只有一个 'top' 标题。使用 names=[coln, coln] 而不是 names=[coln, ''] 导致两列之一被删除(我不知道为什么)。但是,它不是 multi-indexed。换句话说,我无法访问 df['f1']['B'],因为它 returns 错误 KeyError: 'B'。我正在寻找一种方法来实现这一点。通过在 read-in 循环之后转换生成的 df ,或者通过更改循环内的某些内容。

最后,我还想将此数据框导出到 tab-separated 文本文件。

编辑 - 添加单行,归功于@ptrj。

df = pd.concat([df1.set_index('X'),df2.set_index('X')],axis=1,keys = ['F1','F2'])

In []: df
Out[]:
      F1    F2
    B  C  B   C
X
a  0  2  0   4
b  4  9  8  18
z  3  0  6   0

替代解决方案:

您可以从数组定义 MultiIndex。

让我们从两个示例 DataFrame 开始。

df1 = pd.DataFrame({'B': {0: 0, 1: 4, 2: 3},
                   'C': {0: 2, 1: 9, 2: 0},
                   'X': {0: 'a', 1: 'b', 2: 'z'}})

df2 = pd.DataFrame({'B': {0: 0, 1: 8, 2: 6},
                   'C': {0: 4, 1: 18, 2: 0},
                   'X': {0: 'a', 1: 'b', 2: 'z'}})

# Merge the DataFrames
merged = df1.merge(df2,on='X').set_index('X')

# Create a MultiIndex
arrays = [['F1','F1','F2','F2'], ['B','C','B','C']]
columns = pd.MultiIndex.from_arrays(arrays, names=['level1', 'level2'])

# Create your DataFrame    

df = pd.DataFrame(data=merged.as_matrix(),
                  columns=columns,
                  index = df1['X'])

df 现在看起来像:

level1    F1      F2
level2  B   C   B   C
    X               
    a   0   2   0   4
    b   4   9   8   18
    z   3   0   6   0

现在,您可以使用 df['F1']

对其进行索引
level2  B   C
   X        
   a    0   2
   b    4   9
   z    3   0

或者,df['F1']['B'],它给你:

0    0
1    4
2    3

编辑:@Bram Vanroy extended this solution 使用多个 DataFrame。