Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 熊猫读取带空格的多索引csv_Python_Python 2.7_Csv_Pandas - Fatal编程技术网

Python 熊猫读取带空格的多索引csv

Python 熊猫读取带空格的多索引csv,python,python-2.7,csv,pandas,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 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,

我正在努力正确加载一个csv,它有一个带有空格的多行标题。CSV如下所示:

,,C,,,D,,
A,B,X,Y,Z,X,Y,Z
1,2,3,4,5,6,7,8
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])

我想得到的是:

当我尝试加载
pd.read_csv(文件头=[0,1],sep=',')
时,我最终得到以下结果:

有没有办法得到想要的结果


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


使用的版本:

  • Python:2.7.8
  • 熊猫0.16.0
您可以通过以下方式阅读:

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

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

没有神奇的方法可以让pandas知道您希望索引的外观,最接近的方法是自己指定很多,如:

,,C,,,D,,
A,B,X,Y,Z,X,Y,Z
1,2,3,4,5,6,7,8
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的前两行,并在加载完整数据集之前循环通过获得的列动态生成names变量

pd.read_csv(file, nrows=1, header=[0,1], index_col=[0, 1])
然后访问列和循环以创建标题。
同样,这不是一个非常干净的解决方案,但应该会起作用。

这里有一个自动修复列索引的方法。第一, 将列级别值拉入数据框:

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')
因此,
现在看起来像

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('')
要使前两列,即
A
B
,可索引为
df['A']
df['B']
——就好像它们是单级的一样——您可以交换第一列和第二列中的值:

columns.loc[mask, [0,1]] = columns.loc[mask, [1,0]].values
现在,您可以构建一个新的多索引并将其分配给
df.columns

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

如果
数据

,,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
然后

屈服

   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

使用多索引加载数据帧:

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)

我使用了一种技术将多索引列展平并生成一列。它对我很有效

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

我得到的结果与我使用
pd.read_csv(file,header=[0,1])得到的结果完全相同。
你能粘贴你的csv文件的样本吗?@unutbu非常友好,在原始问题中添加了csv代码(谢谢!)问题是csv文件:1)有大量列;2) 是由另一个程序自动生成的,因此从一个时间到另一个时间,列将发生变化。我猜有一种方法可以在第一层写一个循环函数,如果是空的,可以重命名为左边的函数或者其他什么?在你写答案的时候,我提出了我自己的解决方案。你的看起来更优雅/泛文化(这是一件事吗?)。谢谢你的回答!唯一需要注意的是,前几列(本例中的A、B)并不总是只有两列。但是你的代码可以很容易地修改来解释这个问题。好的,我已经修改了代码来解决这个问题。我的第一个回答使用了
set\u index
reset\u index
。。。这对性能不太好。新方法只需在创建多索引之前交换
列中的值即可。节省了时间!谢谢