2 回答

TA貢獻(xiàn)1816條經(jīng)驗(yàn) 獲得超4個(gè)贊
在為自己回答這個(gè)問(wèn)題的過(guò)程中,我學(xué)到了很多東西,我想把一組例子和一些解釋放在一起。
levels爭(zhēng)論點(diǎn)的具體答案將走向終點(diǎn)。
pandas.concat:失蹤手冊(cè)
鏈接到當(dāng)前文檔
導(dǎo)入和定義對(duì)象
import pandas as pd
d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), index=[2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), index=[1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), index=[1, 3])
s1 = pd.Series([1, 2], index=[2, 3])
s2 = pd.Series([3, 4], index=[1, 2])
s3 = pd.Series([5, 6], index=[1, 3])
參數(shù)
objs
我們遇到的第一個(gè)論點(diǎn)是objs:
objs:Series,DataFrame或Panel對(duì)象的序列或映射如果傳遞了dict,則排序的鍵將用作keys參數(shù),除非它被傳遞,在這種情況下將選擇值(見下文)。任何None對(duì)象都將被靜默刪除,除非它們都是None,在這種情況下將引發(fā)ValueError
我們通常會(huì)看到這與一個(gè)Series或多個(gè)DataFrame對(duì)象一起使用。
我將展示它dict也非常有用。
發(fā)電機(jī)也可使用,并使用時(shí)可以是有用的map,如map(f, list_of_df)
現(xiàn)在,我們將堅(jiān)持上面定義的一些DataFrame和Series對(duì)象的列表。我將展示如何利用字典來(lái)提供非常有用的MultiIndex結(jié)果。
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
axis
我們遇到的第二個(gè)參數(shù)是axis默認(rèn)值0:
axis:{0 /'index',1 /'columns'},默認(rèn)值0要連接的軸。
兩個(gè)DataFrame帶axis=0(堆疊)
對(duì)于0或index我們的意思是說(shuō):“沿著列對(duì)齊并添加到索引”。
如上所示我們使用的地方axis=0,因?yàn)?是默認(rèn)值,我們看到索引d2擴(kuò)展了索引,d1盡管價(jià)值重疊2:
pd.concat([d1, d2], axis=0)
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
兩個(gè)DataFrames的axis=1(并排)
對(duì)于值1或columns我們的意思是說(shuō):“沿索引對(duì)齊并添加到列”,
pd.concat([d1, d2], axis=1)
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
我們可以看到結(jié)果索引是索引的并集,結(jié)果列是列的擴(kuò)展d1列d2。
兩個(gè)(或三個(gè))Series帶axis=0(堆疊)
當(dāng)結(jié)合pandas.Series一起axis=0,我們得到一個(gè)pandas.Series。由此而來(lái)的名稱Series將是None除非所有Series被合并具有相同的名稱。注意'Name: A'打印出來(lái)的結(jié)果Series。當(dāng)它不存在時(shí),我們可以假設(shè)Series名稱是None。
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename('A'),
pd.concat( | [s1.rename('A'), | [s1.rename('A'), | s2.rename('B'),
[s1, s2]) | s2]) | s2.rename('A')]) | s3.rename('A')])
-------------- | --------------------- | ---------------------- | ----------------------
2 1 | 2 1 | 2 1 | 2 1
3 2 | 3 2 | 3 2 | 3 2
1 3 | 1 3 | 1 3 | 1 3
2 4 | 2 4 | 2 4 | 2 4
dtype: int64 | dtype: int64 | Name: A, dtype: int64 | 1 5
| | | 3 6
| | | dtype: int64
兩個(gè)(或三個(gè))Series與axis=1(并排)
在組合pandas.Series時(shí)axis=1,它是name我們引用的屬性,以便在結(jié)果中推斷列名pandas.DataFrame。
| | pd.concat(
| pd.concat( | [s1.rename('X'),
pd.concat( | [s1.rename('X'), | s2.rename('Y'),
[s1, s2], axis=1) | s2], axis=1) | s3.rename('Z')], axis=1)
---------------------- | --------------------- | ------------------------------
0 1 | X 0 | X Y Z
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 5.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 NaN
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN 6.0
混合Series并DataFrame用axis=0(堆疊)
當(dāng)執(zhí)行a Series和DataFramealong 的串聯(lián)時(shí)axis=0,我們將所有轉(zhuǎn)換Series為單列DataFrames。
請(qǐng)?zhí)貏e注意,這是一個(gè)串聯(lián)axis=0; 這意味著在對(duì)齊列時(shí)擴(kuò)展索引(行)。在下面的例子中,我們看到索引成為[2, 3, 2, 3]一個(gè)不加選擇的索引追加。除非我Series使用參數(shù)強(qiáng)制命名列,否則列不會(huì)重疊to_frame:
pd.concat( |
[s1.to_frame(), d1]) | pd.concat([s1, d1])
------------------------- | ---------------------
0 A B C | 0 A B C
2 1.0 NaN NaN NaN | 2 1.0 NaN NaN NaN
3 2.0 NaN NaN NaN | 3 2.0 NaN NaN NaN
2 NaN 0.1 0.2 0.3 | 2 NaN 0.1 0.2 0.3
3 NaN 0.1 0.2 0.3 | 3 NaN 0.1 0.2 0.3
你可以看到結(jié)果與pd.concat([s1, d1])我自己穿的一樣to_frame。
但是,我可以使用參數(shù)to控制結(jié)果列的名稱to_frame。Series使用該rename方法重命名不會(huì)控制結(jié)果中的列名DataFrame。
# Effectively renames | |
# `s1` but does not align | # Does not rename. So | # Renames to something
# with columns in `d1` | # Pandas defaults to `0` | # that does align with `d1`
pd.concat( | pd.concat( | pd.concat(
[s1.to_frame('X'), d1]) | [s1.rename('X'), d1]) | [s1.to_frame('B'), d1])
---------------------------- | -------------------------- | ----------------------------
A B C X | 0 A B C | A B C
2 NaN NaN NaN 1.0 | 2 1.0 NaN NaN NaN | 2 NaN 1.0 NaN
3 NaN NaN NaN 2.0 | 3 2.0 NaN NaN NaN | 3 NaN 2.0 NaN
2 0.1 0.2 0.3 NaN | 2 NaN 0.1 0.2 0.3 | 2 0.1 0.2 0.3
3 0.1 0.2 0.3 NaN | 3 NaN 0.1 0.2 0.3 | 3 0.1 0.2 0.3
混合Series并DataFrame用axis=1(并排)
這非常直觀。當(dāng)屬性不可用時(shí),Series列名默認(rèn)為此類Series對(duì)象的枚舉name。
| pd.concat(
pd.concat( | [s1.rename('X'),
[s1, d1], | s2, s3, d1],
axis=1) | axis=1)
------------------- | -------------------------------
0 A B C | X 0 1 A B C
2 1 0.1 0.2 0.3 | 1 NaN 3.0 5.0 NaN NaN NaN
3 2 0.1 0.2 0.3 | 2 1.0 4.0 NaN 0.1 0.2 0.3
| 3 2.0 NaN 6.0 0.1 0.2 0.3
join
第三個(gè)參數(shù)是join描述生成的合并是應(yīng)該是外部合并(默認(rèn))還是內(nèi)部合并。
join:{'inner','outer'},默認(rèn)'outer'
如何處理其他軸上的索引。
事實(shí)證明,沒(méi)有l(wèi)eft或right選項(xiàng)pd.concat可以處理多于兩個(gè)要合并的對(duì)象。
在的情況下,d1和d2,選項(xiàng)如下所示:
outer
pd.concat([d1, d2], axis=1, join='outer')
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
inner
pd.concat([d1, d2], axis=1, join='inner')
A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6
join_axes
第四個(gè)論點(diǎn)是允許我們進(jìn)行l(wèi)eft合并的事情。
join_axes:索引對(duì)象列表
用于其他n - 1軸而不是執(zhí)行內(nèi)部/外部設(shè)置邏輯的特定索引。
左合并
pd.concat([d1, d2, d3], axis=1, join_axes=[d1.index])
A B C B C D A B D
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
合并
pd.concat([d1, d2, d3], axis=1, join_axes=[d3.index])
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
ignore_index
ignore_index:boolean,default False
如果為True,則不要使用串聯(lián)軸上的索引值。生成的軸將標(biāo)記為0,...,n - 1.如果要連接并置軸沒(méi)有有意義的索引信息的對(duì)象,這將非常有用。請(qǐng)注意,在連接中仍然遵循其他軸上的索引值。
就像我堆疊在一起d1時(shí)d2,如果我不關(guān)心索引值,我可以重置它們或忽略它們。
| pd.concat( | pd.concat(
| [d1, d2], | [d1, d2]
pd.concat([d1, d2]) | ignore_index=True) | ).reset_index(drop=True)
--------------------- | ----------------------- | -------------------------
A B C D | A B C D | A B C D
2 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6
使用時(shí)axis=1:
| pd.concat(
| [d1, d2], axis=1,
pd.concat([d1, d2], axis=1) | ignore_index=True)
------------------------------- | -------------------------------
A B C B C D | 0 1 2 3 4 5
1 NaN NaN NaN 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 3 0.1 0.2 0.3 NaN NaN NaN
keys
我們可以傳遞標(biāo)量值或元組列表,以便將元組或標(biāo)量值分配給相應(yīng)的MultiIndex。傳遞列表的長(zhǎng)度必須與連接的項(xiàng)目數(shù)相同。
keys:sequence,default None
如果傳遞了多個(gè)級(jí)別,則應(yīng)包含元組。使用傳遞的鍵作為最外層來(lái)構(gòu)造層次索引
axis=0
連接Series對(duì)象時(shí)axis=0(擴(kuò)展索引)。
這些鍵成為MultiIndexindex屬性中對(duì)象的新初始級(jí)別。
# length 3 length 3 # length 2 length 2
# /--------\ /-----------\ # /----\ /------\
pd.concat([s1, s2, s3], keys=['A', 'B', 'C']) pd.concat([s1, s2], keys=['A', 'B'])
---------------------------------------------- -------------------------------------
A 2 1 A 2 1
3 2 3 2
B 1 3 B 1 3
2 4 2 4
C 1 5 dtype: int64
3 6
dtype: int64
但是,我們可以在keys參數(shù)中使用多個(gè)標(biāo)量值來(lái)創(chuàng)建更深層次的值MultiIndex。這里我們傳遞tuples長(zhǎng)度為2的前兩個(gè)新級(jí)別MultiIndex:
pd.concat(
[s1, s2, s3],
keys=[('A', 'X'), ('A', 'Y'), ('B', 'X')])
-----------------------------------------------
A X 2 1
3 2
Y 1 3
2 4
B X 1 5
3 6
dtype: int64
axis=1
沿列擴(kuò)展時(shí)有點(diǎn)不同。當(dāng)我們使用axis=0(見上文)時(shí),我們的keys行為MultiIndex除現(xiàn)有指數(shù)外還作為水平。因?yàn)閍xis=1,我們指的是Series對(duì)象沒(méi)有的軸,即columns屬性。
兩個(gè)的變化Serieswtihaxis=1
請(qǐng)注意,只要沒(méi)有傳遞就命名s1和s2事務(wù)keys,但如果keys傳遞則會(huì)被覆蓋。
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename('U'),
pd.concat( | [s1, s2], | [s1.rename('U'), | s2.rename('V')],
[s1, s2], | axis=1, | s2.rename('V')], | axis=1,
axis=1) | keys=['X', 'Y']) | axis=1) | keys=['X', 'Y'])
-------------- | --------------------- | ---------------------- | ----------------------
0 1 | X Y | U V | X Y
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN
MultiIndex用Series和axis=1
pd.concat(
[s1, s2],
axis=1,
keys=[('W', 'X'), ('W', 'Y')])
-----------------------------------
W
X Y
1 NaN 3.0
2 1.0 4.0
3 2.0 NaN
兩DataFrame帶axis=1
與axis=0示例一樣,keys將級(jí)別添加到a MultiIndex,但這次添加到columns屬性中存儲(chǔ)的對(duì)象。
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
axis=1, | axis=1,
keys=['X', 'Y']) | keys=[('First', 'X'), ('Second', 'X')])
------------------------------- | --------------------------------------------
X Y | First Second
A B C B C D | X X
1 NaN NaN NaN 0.4 0.5 0.6 | A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
| 3 0.1 0.2 0.3 NaN NaN NaN
Series并DataFrame與axis=1
這很棘手。在這種情況下,標(biāo)量密鑰值不能充當(dāng)索引為唯一的水平Series時(shí),它成為一列,同時(shí)還充當(dāng)?shù)牡谝患?jí)對(duì)象MultiIndex的DataFrame。因此,Pandas將再次使用對(duì)象的name屬性Series作為列名的來(lái)源。
pd.concat( | pd.concat(
[s1, d1], | [s1.rename('Z'), d1],
axis=1, | axis=1,
keys=['X', 'Y']) | keys=['X', 'Y'])
--------------------- | --------------------------
X Y | X Y
0 A B C | Z A B C
2 1 0.1 0.2 0.3 | 2 1 0.1 0.2 0.3
3 2 0.1 0.2 0.3 | 3 2 0.1 0.2 0.3
局限keys和MultiIndex差異。
Pandas似乎只是從Series名稱推斷列名,但在具有不同列級(jí)別的數(shù)據(jù)幀之間進(jìn)行類似級(jí)聯(lián)時(shí),它不會(huì)填充空白。
d1_ = pd.concat(
[d1], axis=1,
keys=['One'])
d1_
One
A B C
2 0.1 0.2 0.3
3 0.1 0.2 0.3
然后將其與另一個(gè)數(shù)據(jù)框連接在一起,而對(duì)象中只有一個(gè)級(jí)別,Pandas將拒絕嘗試創(chuàng)建MultiIndex對(duì)象的元組并組合所有數(shù)據(jù)框,就像單個(gè)級(jí)別的對(duì)象,標(biāo)量和元組一樣。
pd.concat([d1_, d2], axis=1)
(One, A) (One, B) (One, C) B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
傳遞dict而不是list
傳遞字典時(shí),pandas.concat將使用字典中的鍵作為keys參數(shù)。
# axis=0 | # axis=1
pd.concat( | pd.concat(
{0: d1, 1: d2}) | {0: d1, 1: d2}, axis=1)
----------------------- | -------------------------------
A B C D | 0 1
0 2 0.1 0.2 0.3 NaN | A B C B C D
3 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
levels
這與keys參數(shù)一起使用。當(dāng)levels保留為默認(rèn)值時(shí)None,Pandas將獲取結(jié)果的每個(gè)級(jí)別的唯一值MultiIndex,并將其用作結(jié)果index.levels屬性中使用的對(duì)象。
級(jí)別:序列列表,默認(rèn)無(wú)
用于構(gòu)造MultiIndex的特定級(jí)別(唯一值)。否則,它們將從鍵中推斷出來(lái)。
如果熊貓已經(jīng)推斷出這些水平應(yīng)該是什么,那么我們有什么優(yōu)勢(shì)來(lái)指定它?我將展示一個(gè)示例,并讓您自己思考為什么這可能有用的其他原因。
例
根據(jù)文檔,levels參數(shù)是序列列表。這意味著我們可以使用另一個(gè)pandas.Index作為其中一個(gè)序列。
考慮作為df串聯(lián)的數(shù)據(jù)框d1,d2并且d3:
df = pd.concat(
[d1, d2, d3], axis=1,
keys=['First', 'Second', 'Fourth'])
df
First Second Fourth
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
列對(duì)象的級(jí)別為:
print(df, *df.columns.levels, sep='\n')
Index(['First', 'Second', 'Fourth'], dtype='object')
Index(['A', 'B', 'C', 'D'], dtype='object')
如果我們sum在一個(gè)內(nèi)部使用groupby我們得到:
df.groupby(axis=1, level=0).sum()
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
但是,如果沒(méi)有['First', 'Second', 'Fourth']其他缺少的類別命名Third和Fifth?我希望它們包含在groupby聚合的結(jié)果中?如果我們有一個(gè),我們可以這樣做pandas.CategoricalIndex。我們可以提前指定levels參數(shù)。
所以相反,我們定義df為:
cats = ['First', 'Second', 'Third', 'Fourth', 'Fifth']
lvl = pd.CategoricalIndex(cats, categories=cats, ordered=True)
df = pd.concat(
[d1, d2, d3], axis=1,
keys=['First', 'Second', 'Fourth'],
levels=[lvl]
)
df
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
但是column對(duì)象的第一級(jí)是:
df.columns.levels[0]
CategoricalIndex(
['First', 'Second', 'Third', 'Fourth', 'Fifth'],
categories=['First', 'Second', 'Third', 'Fourth', 'Fifth'],
ordered=True, dtype='category')
我們的groupby總結(jié)看起來(lái)像:
df.groupby(axis=1, level=0).sum()
First Second Third Fourth Fifth
1 0.0 1.5 0.0 2.4 0.0
2 0.6 1.5 0.0 0.0 0.0
3 0.6 0.0 0.0 2.4 0.0
names
這用于命名結(jié)果的級(jí)別MultiIndex。names列表的長(zhǎng)度應(yīng)與結(jié)果中的級(jí)別數(shù)相匹配MultiIndex。
names:list,default無(wú)
生成的層次結(jié)構(gòu)索引中的級(jí)別的名稱
# axis=0 | # axis=1
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
keys=[0, 1], | axis=1, keys=[0, 1],
names=['lvl0', 'lvl1']) | names=['lvl0', 'lvl1'])
----------------------------- | ----------------------------------
A B C D | lvl0 0 1
lvl0 lvl1 | lvl1 A B C B C D
0 2 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
2 NaN 0.4 0.5 0.6 |
verify_integrity
自解釋文件
verify_integrity:boolean,default False
檢查新的連鎖軸是否包含重復(fù)項(xiàng)。相對(duì)于實(shí)際數(shù)據(jù)連接,這可能非常昂貴。
因?yàn)閺拇?lián)結(jié)果索引d1和d2不唯一,它會(huì)失敗的完整性檢查。
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
和
pd.concat([d1, d2], verify_integrity=True)
> ValueError:索引具有重疊值:[2]

TA貢獻(xiàn)2011條經(jīng)驗(yàn) 獲得超2個(gè)贊
對(duì)于社區(qū)而言,簡(jiǎn)單地執(zhí)行拉取請(qǐng)求以向主文檔添加一些缺少的示例(僅一對(duì))真的會(huì)更有用; SO只能搜索而不能瀏覽; 進(jìn)一步建立文檔的鏈接在這里很有用 - 絕大多數(shù)已經(jīng)很好并且完全記錄在案
添加回答
舉報(bào)