この質問に自分で答える過程で多くのことを学びました。例のカタログといくつかの説明をまとめたかったのです。
のポイントへの具体的な答え levels
議論は終わりに近づくでしょう。
pandas.concat
:不足しているマニュアル
現在のドキュメントへのリンク
オブジェクトのインポートと定義
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])
議論
objs
私たちが遭遇する最初の議論はobjs
:
objs:Series、DataFrame、またはPanelオブジェクトのシーケンスまたはマッピング。dictが渡された場合、ソートされたキーがキー引数として使用されますが、渡されない場合は値が選択されます(以下を参照)。NoneオブジェクトがすべてNoneでない限り、Noneオブジェクトはサイレントにドロップされます。その場合、ValueErrorが発生します。
- 通常、これは
Series
またはDataFrame
オブジェクトのリストで使用されます。
- それ
dict
も非常に役立つことを示します。
- 発電機を使用することもできるし、使用する際に有用であり得る
map
とmap(f, list_of_df)
ここでは、上で定義したDataFrame
とSeries
オブジェクトの一部のリストを使います。辞書を活用して、非常に有用なMultiIndex
結果を後から得る方法を紹介します。
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
私たちが遭遇する2番目の引数はaxis
、デフォルト値が0
次のとおりです。
axis:{0 / 'index'、1 / 'columns'}、デフォルト0連結する軸。
2つDataFrame
のs axis=0
(スタック)
の値の場合、0
またはindex
「列に沿って配置し、インデックスに追加する」と言います。
上で使用したように、がデフォルト値なaxis=0
ので0
、がデフォルト値であり、の値が重複しているd2
にd1
もかかわらず、のインデックスがのインデックスを拡張していることがわかります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
2つDataFrame
のs axis=1
(並べて)
値の場合、1
またはcolumns
「インデックスに沿って配置し、列に追加する」と言います。
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
結果のインデックスはインデックスの和集合であり、結果の列はの列による列の拡張であることがわかりd1
ますd2
。
2(または3)Series
とaxis=0
(スタック)
pandas.Series
一緒axis=0
に組み合わせると、が返されますpandas.Series
。結合Series
されるNone
すべてSeries
が同じ名前でない限り、結果の名前はになります。'Name: A'
結果を印刷するときに注意してくださいSeries
。存在しない場合、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
2つ(または3つ)Series
とaxis=1
(並べて)
pandas.Series
一緒axis=1
に組み合わせる場合name
、結果の列名を推測するために参照する属性です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
(スタック)
a Series
とDataFrame
alongの連結を実行するときaxis=0
、すべてSeries
を単一の列DataFrame
sに変換します。
これは連結になっていることに特に注意してくださいaxis=0
。つまり、列を揃えながらインデックス(行)を拡張します。以下の例では、インデックスが[2, 3, 2, 3]
無差別に追加されるインデックスになります。Series
引数を指定して列の名前を強制しない限り、列は重複しません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
結果pd.concat([s1, d1])
は、私が実行した場合と同じです。to_frame
自分でです。
ただし、結果の列の名前をへのパラメーターで制御できますto_frame
。メソッドでの名前を変更しSeries
ても、結果のの列名は制御されrename
ません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
(並べて)
これはかなり直感的です。属性が使用できない場合、Series
列名はデフォルトでそのようなSeries
オブジェクトの列挙に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
3番目の引数はjoin
、結果のマージが外部マージ(デフォルト)か内部マージかを示します。
join:{'inner'、 'outer'}、デフォルトは 'outer'
他の軸のインデックスを処理する方法。
それは、判明していない何があるleft
か、right
オプションとしてpd.concat
以上のマージにちょうど2つのオブジェクトよりも処理することができます。
d1
およびの場合d2
、オプションは次のようになります。
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
4番目の引数は、left
マージなどを可能にするものです。
join_axes:インデックスオブジェクトのリスト
内側/外側のセットロジックを実行する代わりに、他のn-1軸に使用する特定のインデックス。
左マージ
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:ブール値、デフォルトはFalse
Trueの場合、連結軸に沿ってインデックス値を使用しません。結果の軸には0、...、n-1というラベルが付けられます。これは、連結軸に意味のあるインデックス情報がないオブジェクトを連結する場合に役立ちます。他の軸のインデックス値は、結合でも考慮されます。
のd1
上にスタックするときのようにd2
、インデックス値を気にしない場合、それらをリセットするか無視することができます。
| 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
そして使用するとき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
タプルまたはスカラー値を対応するMultiIndexに割り当てるために、スカラー値またはタプルのリストを渡すことができます。渡されるリストの長さは、連結されるアイテムの数と同じ長さでなければなりません。
keys:シーケンス、デフォルトなし
複数のレベルが渡された場合、タプルを含める必要があります。渡されたキーを最外部レベルとして使用して階層インデックスを構築します
axis=0
Series
オブジェクトを連結するときaxis=0
(インデックスを拡張するとき)。
これらのキーMultiIndex
は、index属性のオブジェクトの新しい初期レベルになります。
# 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
引数にスカラー値以上のものを使用して、さらに深いを作成できますMultiIndex
。ここではtuples
、長さ2 を渡し、aの2つの新しいレベルを追加します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
列に沿って拡張する場合は少し異なります。使用した場合axis=0
(上記を参照)、既存のインデックスに加えてレベルkeys
としても機能しましたMultiIndex
。以下のためにaxis=1
、私たちはその軸を参照しているSeries
オブジェクトが持っていない、すなわちcolumns
属性。
2つの
Series
バリエーション
axis=1
が渡されない限り、s1
との命名がs2
重要keys
ですkeys
が、渡された場合は上書きされます。
| | | 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
レベルをに追加しますMultiIndex
が、今回はcolumns
属性に格納されているオブジェクトに追加します。
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
これはトリッキーです。この場合、スカラーキー値のインデックスのレベルのみとして作用することができないSeries
、また最初のレベルとして動作しながら、列になったときにオブジェクトMultiIndex
のためDataFrame
。そのため、Pandasは再びオブジェクトのname
属性をSeries
列名のソースとして使用します。
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
推論。
パンダは名前から列名を推測するだけのようですがSeries
、列レベルの数が異なるデータフレーム間で同様の連結を行う場合、空白は埋められません。
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
次に、これを列オブジェクトのレベルが1つだけの別のデータフレームと連結します。Pandasは、MultiIndex
オブジェクトのタプルを作成してすべてのデータフレームを1つのレベルのオブジェクト、スカラー、およびタプルのように結合することを拒否します。
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
辞書を渡すとき、は辞書pandas.concat
からのキーをkeys
パラメーターとして使用します。
# 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
引数と組み合わせて使用されlevels
ます。がのデフォルト値として残されている場合None
、Pandasは結果の各レベルの一意の値を取得MultiIndex
し、結果のindex.levels
属性で使用されるオブジェクトとして使用します。
levels:シーケンスのリスト、デフォルトなし
MultiIndexの構築に使用する特定のレベル(一意の値)。それ以外の場合は、キーから推測されます。
パンダがすでにこれらのレベルがどうあるべきかを推測している場合、それを自分で指定することにはどのような利点がありますか?1つの例を示し、これが役立つかもしれない他の理由を考えるためにあなたにそれを任せます。
例
ドキュメントによれば、levels
引数はシーケンスのリストです。これは、別のpandas.Index
、それらのシーケンスの1つとしてのものをます。
データフレームを検討df
の連結である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
列オブジェクトのレベルは次のとおりです。
print(df, *df.columns.levels, sep='\n')
Index(['First', 'Second', 'Fourth'], dtype='object')
Index(['A', 'B', 'C', 'D'], dtype='object')
sum
内で使用すると、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
しかし、['First', 'Second', 'Fourth']
別のカテゴリが見つからずThird
、and という名前の場合はどうなりFifth
ますか?そして、それらをgroupby
集計の結果に含めたいですか?もし私たちが持っていれば、これを行うことができますpandas.CategoricalIndex
。そして、それを前もって指定することができますlevels
引数。
代わりに、次のように定義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
しかし、列オブジェクトの最初のレベルは次のとおりです。
df.columns.levels[0]
CategoricalIndex(
['First', 'Second', 'Third', 'Fourth', 'Fifth'],
categories=['First', 'Second', 'Third', 'Fourth', 'Fifth'],
ordered=True, dtype='category')
そして、私たちのgroupby
合計は次のようになります:
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
これは、結果のレベルに名前を付けるために使用されますMultiIndex
。names
リストの長さは、結果のレベル数と一致する必要がありますMultiIndex
。
names:リスト、デフォルトなし
結果の階層インデックスのレベルの名前
# 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
新しい連結軸に重複が含まれているかどうかを確認します。これは、実際のデータ連結に比べて非常に高価になる可能性があります。
連結の結果のインデックスのでd1
とd2
一意ではありません、それは整合性チェックを失敗していました。
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]