将文件合并到 python 中的 multiIndex 数据帧,最后导出到 txt
Combining files into multiIndex dataframe in python and finally export to txt
我有几个文件都具有相同的第一列 (X
) 和相同的列名 (X
、B
、C
) , 但第二列和第三列是不同的值。
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。
我有几个文件都具有相同的第一列 (X
) 和相同的列名 (X
、B
、C
) , 但第二列和第三列是不同的值。
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。