[英]How to concatenate pandas dataframes with automatic keys?
我有
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
使用相同的 function。
我怎樣才能正確地做到這一點?
編輯:折扣 - 我只能使用遞增的 function 進行管理。它不必與單級 dfs 一起使用,但如果可以的話會很好。
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
list
的數據幀,則結果 dataframe 已經被排序
我的方法是嵌套兩個pd.concat
函數,第二個函數從單個索引創建MultiIndex
dataframe。
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
並合並一個新的 dataframe:
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 的評論說這種方法效率低下,進行了一些簡單的測試。 這是 output:
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)
我就是這樣解決的
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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.