pandas 数据框的连接列表,但忽略列名

Concat list of pandas data frame, but ignoring column name

Sub-title: 把它装傻pandas,别耍小聪明了。

我有一个 single-column pandas 数据框的列表 (res),每个数据框都包含相同类型的数字数据,但每个都有不同的列名。行索引没有意义。我想将它们放入一个非常长的 single-column 数据框中。

当我执行 pd.concat(res) 时,每个输入文件得到一列(以及 NaN 单元格的加载和加载)。我已经为参数 (*) 尝试了各种值,但 none 满足了我的要求。

编辑:示例数据:

res = [
    pd.DataFrame({'A':[1,2,3]}),
    pd.DataFrame({'B':[9,8,7,6,5,4]}),
    pd.DataFrame({'C':[100,200,300,400]}),
]

我有一个ugly-hack解决方案:复制每个数据框并给它一个新的列名:

newList = []
for r in res:
  r.columns = ["same"]
  newList.append(r)
pd.concat( newList, ignore_index=True )

当然这不是最好的方法??

顺便说一句, 类似,但我的问题更简单,因为我不想维护索引。 (我也从 N single-column 个数据帧的列表开始,而不是单个 N-column 个数据帧。)

*:例如axis=0 是默认行为。 axis=1报错。 join="inner" 很傻(我只得到索引)。 ignore_index=True 对索引重新编号,但我仍然得到很多列,很多 NaN。


更新空列表

当数据有一个空列表时,我遇到了问题(所有给定的解决方案),例如:

res = [
    pd.DataFrame({'A':[1,2,3]}),
    pd.DataFrame({'B':[9,8,7,6,5,4]}),
    pd.DataFrame({'C':[]}),
    pd.DataFrame({'D':[100,200,300,400]}),
]

诀窍是通过添加 .astype('float64') 强制类型。例如

pd.Series(np.concatenate([df.values.ravel().astype('float64') for df in res]))

或:

pd.concat(res,axis=0).astype('float64').stack().reset_index(drop=True)

我觉得你需要concat with stack:

print (pd.concat(res, axis=1))
     A  B      C
0  1.0  9  100.0
1  2.0  8  200.0
2  3.0  7  300.0
3  NaN  6  400.0
4  NaN  5    NaN
5  NaN  4    NaN

print (pd.concat(res, axis=1).stack().reset_index(drop=True))
0       1.0
1       9.0
2     100.0
3       2.0
4       8.0
5     200.0
6       3.0
7       7.0
8     300.0
9       6.0
10    400.0
11      5.0
12      4.0
dtype: float64

另一种 numpy.ravel 的扁平化解决方案:

print (pd.Series(pd.concat(res, axis=1).values.ravel()).dropna())
0       1.0
1       9.0
2     100.0
3       2.0
4       8.0
5     200.0
6       3.0
7       7.0
8     300.0
10      6.0
11    400.0
13      5.0
16      4.0
dtype: float64

print (pd.DataFrame(pd.concat(res, axis=1).values.ravel(), columns=['col']).dropna())
      col
0     1.0
1     9.0
2   100.0
3     2.0
4     8.0
5   200.0
6     3.0
7     7.0
8   300.0
10    6.0
11  400.0
13    5.0
16    4.0

list comprehension 的解决方案:

print (pd.Series(np.concatenate([df.values.ravel() for df in res])))
0       1
1       2
2       3
3       9
4       8
5       7
6       6
7       5
8       4
9     100
10    200
11    300
12    400
dtype: int64 

我会使用列表理解,例如:

import pandas as pd
res = [
    pd.DataFrame({'A':[1,2,3]}),
    pd.DataFrame({'B':[9,8,7,6,5,4]}),
    pd.DataFrame({'C':[100,200,300,400]}),
]


x = []
[x.extend(df.values.tolist()) for df in res]
pd.DataFrame(x)

Out[49]: 
      0
0     1
1     2
2     3
3     9
4     8
5     7
6     6
7     5
8     4
9   100
10  200
11  300
12  400

我给你测试了速度

%timeit x = []; [x.extend(df.values.tolist()) for df in res]; pd.DataFrame(x)
10000 loops, best of 3: 196 µs per loop
%timeit pd.Series(pd.concat(res, axis=1).values.ravel()).dropna()
1000 loops, best of 3: 920 µs per loop
%timeit pd.concat(res, axis=1).stack().reset_index(drop=True)
1000 loops, best of 3: 902 µs per loop
%timeit pd.DataFrame(pd.concat(res, axis=1).values.ravel(), columns=['col']).dropna()
1000 loops, best of 3: 1.07 ms per loop
%timeit pd.Series(np.concatenate([df.values.ravel() for df in res]))
10000 loops, best of 3: 70.2 µs per loop

看起来像

pd.Series(np.concatenate([df.values.ravel() for df in res]))

最快。