Pandas - 按行交错/压缩两个DataFrame

时间:2017-08-08 10:01:46

标签: python pandas dataframe

假设我有两个数据帧:

>> df1

   0  1  2
0  a  b  c
1  d  e  f

>> df2

   0  1  2
0  A  B  C
1  D  E  F

如何交错行?即获取此信息:

>> interleaved_df

   0  1  2
0  a  b  c
1  A  B  C
2  d  e  f
3  D  E  F

(注意我的真实DF具有相同的列,但行数不同)。

我尝试了什么

this question的启发(非常相似,但要求):

import pandas as pd
from itertools import chain, zip_longest

df1 = pd.DataFrame([['a','b','c'], ['d','e','f']])  
df2 = pd.DataFrame([['A','B','C'], ['D','E','F']])

concat_df = pd.concat([df1,df2])

new_index = chain.from_iterable(zip_longest(df1.index, df2.index))
# new_index now holds the interleaved row indices

interleaved_df = concat_df.reindex(new_index)

ValueError: cannot reindex from a duplicate axis

最后一次调用失败,因为df1和df2有一些相同的索引值(我的真实DF也是如此)。

有什么想法吗?

5 个答案:

答案 0 :(得分:11)

您可以在连接后对索引进行排序,然后重置索引,即

import pandas as pd

df1 = pd.DataFrame([['a','b','c'], ['d','e','f']])  
df2 = pd.DataFrame([['A','B','C'], ['D','E','F']])

concat_df = pd.concat([df1,df2]).sort_index().reset_index(drop=True)

输出:

   0  1  2
0  a  b  c
1  A  B  C
2  d  e  f
3  D  E  F

编辑(OmerB):无论指数值如何,都要保持秩序。

import pandas as pd
df1 = pd.DataFrame([['a','b','c'], ['d','e','f']]).reset_index()  
df2 = pd.DataFrame([['A','B','C'], ['D','E','F']]).reset_index()

concat_df = pd.concat([df1,df2]).sort_index().set_index('index')

答案 1 :(得分:4)

使用toolz.interleave

In [1024]: from toolz import interleave

In [1025]: pd.DataFrame(interleave([df1.values, df2.values]))
Out[1025]:
   0  1  2
0  a  b  c
1  A  B  C
2  d  e  f
3  D  E  F

答案 2 :(得分:1)

这里是@Bharath答案的扩展,可以使用pd.MultiIndex应用于具有用户定义的索引的DataFrame,而不会丢失它们。

使用完整的列/索引标签和名称定义数据框:

df1 = pd.DataFrame([['a','b','c'], ['d','e','f']], index=['one', 'two'], columns=['col_a', 'col_b','col_c'])  
df1.columns.name = 'cols'
df1.index.name = 'rows'
df2 = pd.DataFrame([['A','B','C'], ['D','E','F']], index=['one', 'two'], columns=['col_a', 'col_b','col_c'])
df2.columns.name = 'cols'
df2.index.name = 'rows'

将DataFrame ID添加到MultiIndex:

df1.index = pd.MultiIndex.from_product([[1], df1.index], names=["df_id", df1.index.name])
df2.index = pd.MultiIndex.from_product([[2], df2.index], names=["df_id", df2.index.name])

然后使用@Bharath的concat()sort_index()

data = pd.concat([df1, df2], axis=0, sort=True)
data.sort_index(axis=0, level=data.index.names[::-1], inplace=True)

输出:

cols       col_a col_b col_c
df_id rows                  
1     one      a     b     c
2     one      A     B     C
1     two      d     e     f
2     two      D     E     F

答案 3 :(得分:0)

您可以尝试这种方式:

In [31]: from toolz import interleave
    ...: import pandas as pd
    ...: from itertools import chain, zip_longest
    ...: 
    ...: df1 = pd.DataFrame([['a','b','c'], ['d','e','f']])  
    ...: df2 = pd.DataFrame([['A','B','C'], ['D','E','F']])

In [32]: concat_df = pd.concat([df1,df2]).sort_index()
    ...: 

In [33]: interleaved_df = concat_df.reset_index(drop=1)

In [34]: interleaved_df
Out[34]: 
   0  1  2
0  a  b  c
1  A  B  C
2  d  e  f
3  D  E  F

答案 4 :(得分:0)

您还可以预先分配新的export XDEBUG_CONFIG="idekey=PHPSTORM" ,然后使用切片填充它。

DataFrame

预分配代码取自this question

虽然对于某些数据类型/大小,它有可能胜过索引方法,但如果DataFrame具有不同的大小,它将无法正常运行。

注意 - 对于具有20列混合字符串,整数和浮动类型的~200000行,索引方法快约5倍。