熊猫用空白读取多索引csv

时间:2015-05-19 10:06:43

标签: python python-2.7 csv pandas

我正在努力正确加载一个带有空格的多行标题的csv。 CSV看起来像这样:

,,C,,,D,,
A,B,X,Y,Z,X,Y,Z
1,2,3,4,5,6,7,8

CSV Header

我想得到的是:

Desired Pandas Header

当我尝试使用pd.read_csv(file, header=[0,1], sep=',')加载时,我最终得到以下内容:

Incorrect result

有没有办法获得理想的结果?

注意:或者,我会接受这个结果:

Alternative result

使用的版本:

  • Python:2.7.8
  • Pandas 0.16.0

5 个答案:

答案 0 :(得分:7)

这是一种修复列索引的自动方法。第一, 将列级值拉入DataFrame:

columns = pd.DataFrame(df.columns.tolist())

然后将Unnamed:列重命名为NaN

columns.loc[columns[0].str.startswith('Unnamed:'), 0] = np.nan

然后向前填充NaN:

columns[0] = columns[0].fillna(method='ffill')

以便columns现在看起来像

In [314]: columns
Out[314]: 
     0  1
0  NaN  A
1  NaN  B
2    C  X
3    C  Y
4    C  Z
5    D  X
6    D  Y
7    D  Z

现在我们可以找到剩余的NaN并用空字符串填充它们:

mask = pd.isnull(columns[0])
columns[0] = columns[0].fillna('')

要设置前两列,AB,可转发为df['A']df['B'] - 就好像它们是单一的 - 你可以交换第一列和第二列中的值:

columns.loc[mask, [0,1]] = columns.loc[mask, [1,0]].values

现在您可以构建一个新的MultiIndex并将其分配给df.columns

df.columns = pd.MultiIndex.from_tuples(columns.to_records(index=False).tolist())

如果data

,请将所有内容放在一起
,,C,,,D,,
A,B,X,Y,Z,X,Y,Z
1,2,3,4,5,6,7,8
3,4,5,6,7,8,9,0

然后

import numpy as np
import pandas as pd
df = pd.read_csv('data', header=[0,1], sep=',')
columns = pd.DataFrame(df.columns.tolist())
columns.loc[columns[0].str.startswith('Unnamed:'), 0] = np.nan
columns[0] = columns[0].fillna(method='ffill')
mask = pd.isnull(columns[0])
columns[0] = columns[0].fillna('')
columns.loc[mask, [0,1]] = columns.loc[mask, [1,0]].values
df.columns = pd.MultiIndex.from_tuples(columns.to_records(index=False).tolist())
    print(df)

产量

   A  B  C        D      
         X  Y  Z  X  Y  Z
0  1  2  3  4  5  6  7  8
1  3  4  5  6  7  8  9  0

答案 1 :(得分:1)

没有神奇的方法可以让大熊猫知道你希望你的索引看起来如何,你最接近的方法就是自己指定一个,比如:

names = ['A', 'B', 
         ('C','X'), ('C', 'Y'), ('C', 'Z'),
         ('D','X'), ('D','Y'), ('D', 'Z')]
pd.read_csv(file, mangle_dupe_cols=True,
            header=1, names=names, index_col=[0, 1])

给予:

     C        D      
     X  Y  Z  X  Y  Z
A B                  
1 2  3  4  5  6  7  8

要以动态方式执行此操作,您可以按原样读取CSV的前两行,并在加载完整数据集之前循环遍历您生成名称变量的列。

pd.read_csv(file, nrows=1, header=[0,1], index_col=[0, 1])

然后访问列并循环以创建标题。 同样,这不是一个非常干净的解决方案,但应该有效。

答案 2 :(得分:0)

你可以阅读:

    df = pd.read_csv('file.csv', header=[0, 1], skipinitialspace=True, tupleize_cols=True)

然后

    df.columns = pd.MultiIndex.from_tuples(df.columns)

答案 3 :(得分:0)

使用multiindex加载数据框:

df = pd.read_csv(filelist,header=[0,1], sep=',')

编写一个替换索引的函数:

def replace_index(df):
    arr = df.columns.values
    l = [list(x) for x in arr]
    for i in range(len(l)):
        if l[i][0][:7] == 'Unnamed':
            if l[i-1][0][:7] != 'Unnamed':
                l[i][0] = l[i-1][0]
    for i in range(len(l)):
        if l[i][0][:7] == 'Unnamed':
                l[i][0] = l[i][1]
                l[i][1] = ''
    index = pd.MultiIndex.from_tuples(l)
    df.columns = index
    return df

返回正确编入索引的新数据框:

replace_index(df)

答案 4 :(得分:0)

我使用了一种从多索引列进行展平并制作一个列的技术。对我来说很好。

your_df.columns = ['_'.join(col).strip() for col in your_df.columns.values]