高效扁平化大熊猫数据帧

时间:2018-01-13 21:43:46

标签: python pandas numpy

我有一个pandas数据帧。它看起来像这样:

pd.DataFrame(data=np.arange(1,10).reshape(3,3), index=['A', 'B', 'C'], columns=['A', 'B', 'C'])

但有100行和100列。

我想压扁它,所以它看起来像这样:

pd.DataFrame({'row' : ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'], 'col' : ['A', 'B', 'C']*3, 'val' : np.arange(1,10)})

最有效的方法是什么?

谢谢,

杰克

3 个答案:

答案 0 :(得分:7)

选项1
不是100%确定效率,但最简单的方法是使用 df.melt

df.rename_axis('row')\
  .reset_index()\
  .melt('row', value_name='val', var_name='col')\
  .sort_values(['row', 'col'])

  row col  val
0   A   A    1
3   A   B    2
6   A   C    3
1   B   A    4
4   B   B    5
7   B   C    6
2   C   A    7
5   C   B    8
8   C   C    9

选项2
使用 stack -

的另一个简单选项
v = df.stack().reset_index()
v.columns=['row', 'col', 'val']
v

或者,

df.stack().rename_axis(['row', 'col']).reset_index(name='val')

  row col  val
0   A   A    1
1   A   B    2
2   A   C    3
3   B   A    4
4   B   B    5
5   B   C    6
6   C   A    7
7   C   B    8
8   C   C    9

答案 1 :(得分:3)

方法#1

NumPy方法 -

# https://stackoverflow.com/a/11146645/ @senderle
def cartesian_product(*arrays):
    la = len(arrays)
    dtype = np.result_type(*arrays)
    arr = np.empty([len(a) for a in arrays] + [la], dtype=dtype)
    for i, a in enumerate(np.ix_(*arrays)):
        arr[...,i] = a
    return arr.reshape(-1, la)

def flatten_dataframe(df):
    c = df.columns.values.astype(str)
    i = df.index.values.astype(str)
    df_out = pd.DataFrame(cartesian_product(i,c),columns=[['row','col']])
    df_out['val'] = df.values.ravel()
    return df_out 

示例运行 -

In [598]: df
Out[598]: 
   A  B  C
P  1  2  3
Q  4  5  6
R  7  8  9

In [599]: flatten_dataframe(df)
Out[599]: 
  row col  val
0   P   A    1
1   P   B    2
2   P   C    3
3   Q   A    4
4   Q   B    5
5   Q   C    6
6   R   A    7
7   R   B    8
8   R   C    9

方法#2:object dtype dataframe

如果你对object dtype数据框没问题,可采用另一种方法 -

def flatten_dataframe_obj(df):
    c = df.columns.values.astype(str)
    i = df.index.values.astype(str)
    m = len(i)
    n = len(c)
    out = np.empty((m,n,3),dtype=object)
    out[...,0] = i[:,None]
    out[...,1] = c
    out[...,2] = df.values
    return pd.DataFrame(out.reshape(-1,3), columns=[['row','col','val']])

答案 2 :(得分:3)

这应该很快:-)

new_df=pd.DataFrame({'row':df.index.repeat(df.shape[1]),'col':df.columns.tolist()*len(df),'val':np.concatenate(df.values)})
new_df
Out[343]: 
  col row  val
0   A   A    1
1   B   A    2
2   C   A    3
3   A   B    4
4   B   B    5
5   C   B    6
6   A   C    7
7   B   C    8
8   C   C    9