如何用自动键连接数据帧?

2024-04-19 05:06:06 发布

您现在位置:Python中文网/ 问答频道 /正文

an earlier question之后

我有

df1 = pd.Dataframe(
    [
    {'a': 1},
    {'a': 2},
    {'a': 3},
    ]
)

df2 = pd.Dataframe(
    [
    {'a': 4},
    {'a': 5},
    ]
)

我想要

 df_id  a
 1      1
        2
        3
 2      4
        5

我太快接受了一个答案,这让我不得不这么做

pd.concat([df1, df2], keys=[1,2])

这给出了正确的结果,但[1,2]是硬编码的

我也希望这是渐进的,意思是给定的

df3

 df_id  a
 1      1
        2
        3
 2      4
        5

df4 = pd.Dataframe(
    [
    {'a': 6},
    {'a': 7},
    ]
)

我希望连接能够提供

 df_id  a
 1      1
        2
        3
 2      4
        5
 3      6
        7

使用相同的函数

我怎样才能正确地做到这一点


编辑:折扣-我只能使用递增功能进行管理。它不必与单级dfs一起工作,但如果它能够工作,那就太好了


Tags: 答案aniddataframe编码dfkeyspd
3条回答

我就是这样解决的

import pandas as pd

df1 = pd.DataFrame(
    [
    {'a': 1},
    {'a': 2},
    {'a': 3},
    ]
)

df2 = pd.DataFrame(
    [
    {'a': 4},
    {'a': 5},
    ]
)

df = df1.append(df2)

df['from'] = df.index == 0
df['from'] = df['from'].cumsum()
df = df[['from', 'a']]

print(df)

我的方法是嵌套两个pd.concat函数,第二个是从单个索引创建MultiIndex数据帧

import pandas as pd

df = pd.DataFrame(
    [
    {'a': 1},
    {'a': 2},
    {'a': 3},
    ]
)

df2 = pd.DataFrame(
    [
    {'a': 4},
    {'a': 5},
    ]
)

df = pd.concat([df, df2], keys=df.index.get_level_values(0))
In[2]: df
Out[2]:
     a
0 0  1
  1  2
  2  3
1 0  4
  1  5

要合并新的数据帧,请执行以下操作:

df3 = pd.DataFrame(
    [
    {'a': 6},
    {'a': 7},
    ]
)

In[3]: pd.concat([df, pd.concat([df3,], keys=(max(df.index.get_level_values(0))+1,))])
Out[3]: 
     a
0 0  1
  1  2
  2  3
1 0  4
  1  5
2 0  6
  1  7

编辑:根据ansev的评论,该方法效率低下,运行了一些简单的测试。这是输出:

In[5]: %timeit pd.concat([df, pd.concat([df3,], keys=(max(df.index.get_level_values(0))+1,))])
Out[5]: 1.99 ms ± 98.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

与他的方法相比:

In[6]: %timeit [myconcat(l1), df3]
Out[6]: 1.92 ms ± 96.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

IIUC

def split_list_by_multitindex(l):

    l_multi, l_not_multi = [], []
    for df in l:
        if isinstance(df.index, pd.MultiIndex):
            l_multi.append(df)
        else:
            l_not_multi.append(df)
    
    return l_multi, l_not_multi

def get_start_key(df):
    return df.index.get_level_values(0)[-1]

def concat_starting_by_key(l, key):
    return pd.concat(l, keys=range(key, key+len(l))) \
        if len(l) > 1 else set_multiindex_in_df(l[0], key)

def set_multiindex_in_df(df, key):
    return df.set_axis(pd.MultiIndex.from_product(([key], df.index)))


def myconcat(l):
    l_multi, l_not_multi = split_list_by_multitindex(l)
    return pd.concat([*l_multi, 
                      concat_starting_by_key(l_not_multi, 
                                              get_start_key(l_multi[-1]) + 1)
                     ]) if l_multi else concat_starting_by_key(l_not_multi, 1)
    
    
    

示例

l1 = [df1, df2]

print(myconcat(l1))

     a
1 0  1
  1  2
  2  3
2 0  4
  1  5

l2 = [myconcat(l1), df4]

print(myconcat(l2))

     a
1 0  1
  1  2
  2  3
2 0  4
  1  5
3 0  6
  1  7

myconcat([df4, myconcat([df1, df2]), df1, df2])

     a
1 0  1
  1  2
  2  3
2 0  4
  1  5
3 0  6
  1  7
4 0  1
  1  2
  2  3
5 0  4
  1  5

注意

这假设如果我们对属于l_multi{}的数据帧进行串联,则生成的数据帧将已经排序

相关问题 更多 >