質問
- どうやって使うんですか
pd.concat
? - 議論の根拠は何ですか
levels
? - 議論の根拠は何ですか
keys
? - すべての引数の使用方法を説明するのに役立つ例がたくさんありますか?
パンダのconcat
機能はスイスアーミーナイフマージ ユーティリティの です。これが役立つ状況は多岐にわたります。既存のドキュメントでは、オプションの引数のいくつかの詳細が省略されています。その中には、 およびlevels
引数がありますkeys
。私は、これらの引数が何をするのか理解しようとしました。
のさまざまな側面を理解するための入り口となる質問をしたいと思いますpd.concat
。
データフレームd1
、、d2
およびを考えますd3
。
import pandas as pd
d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), [2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), [1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), [1, 3])
これらを連結すると
pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'])
pandas.MultiIndex
オブジェクトに対して を使用すると、期待どおりの結果が得られましたcolumns
。
A B C D
d1 2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
d2 1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
d3 1 0.7 0.8 NaN 0.9
3 0.7 0.8 NaN 0.9
しかし、私はlevels
引数のドキュメント:
レベル: シーケンスのリスト、デフォルトは None。MultiIndex の構築に使用する特定のレベル (一意の値)。それ以外の場合は、キーから推測されます。
だから合格した
pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2']])
そして、KeyError
ValueError: Key d3 not in level Index(['d1', 'd2'], dtype='object')
これは理にかなっています。私が渡したレベルは、キーによって示される必要なレベルを説明するには不十分でした。私が上記のように何も渡さなかった場合、レベルは推測されます (ドキュメントに記載されているとおり)。しかし、この引数をより効果的に使用するには他にどのような方法がありますか?
代わりにこれを試した場合:
pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2', 'd3']])
上記と同じ結果が得られました。しかし、レベルにもう1つの値を追加すると、
df = pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2', 'd3', 'd4']])
最終的には同じデータ フレームになりますが、結果にはMultiIndex
未使用のレベルが含まれます。
df.index.levels[0]
Index(['d1', 'd2', 'd3', 'd4'], dtype='object')
それで、議論のポイントは何でありlevel
、別の使い方をすべきでしょうかkeys
?
Python 3.6 と Pandas 0.22 を使用しています。
ベストアンサー1
この質問に自分自身で答える過程で、私は多くのことを学びました。そこで、例と説明のカタログをまとめたいと思いました。
議論の要点に対する具体的な答えは、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
:
オブジェクト: Series、DataFrame、またはPanelオブジェクトのシーケンスまたはマッピング。辞書が渡された場合、ソートされたキーがkeys引数として使用されます。辞書が渡されない場合は、値が選択されます(以下を参照)。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
:
軸: {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
)
Series
との連結DataFrame
を に沿って実行するとaxis=0
、すべてがSeries
単一の列 に変換されますDataFrame
。
これは に沿った連結であることに特に注意してください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
結果のマージが外部マージ (デフォルト) になるか内部マージになるかを説明します。
参加する: {'inner', 'outer'}、デフォルトは 'outer'
他の軸のインデックスを処理する方法。
結局のところ、には 2 つ以上のオブジェクトをマージできるleft
またはright
オプションはありません。pd.concat
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
left
4 番目の引数は、マージなどを実行できるようにするものです。
結合軸: インデックス オブジェクトのリスト
。内部/外部セット ロジックを実行する代わりに、他の 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
無視インデックス: ブール値、デフォルトは 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 にタプルまたはスカラー値を割り当てるために、スカラー値またはタプルのリストを渡すことができます。渡されるリストの長さは、連結される項目の数と同じ長さである必要があります。
キー: シーケンス、デフォルトなし
複数のレベルが渡された場合は、タプルを含める必要があります。渡されたキーを最外部レベルとして使用して階層インデックスを構築します。
axis=0
Series
オブジェクトを連結する場合axis=0
(インデックスを拡張する場合)。
MultiIndex
これらのキーは、インデックス属性内のオブジェクトの新しい初期レベルになります。
# 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 の を渡し、 の 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
Series
2つ のバリエーション
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
2
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
の最初のレベルとしても機能します。そのため、Pandas は、オブジェクトの属性を列名のソースとしてDataFrame
再度使用します。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
。
Pandas は名前から列名を推測するだけのように見えます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
、すべてのデータ フレームを単一レベルのオブジェクト、スカラー、タプルであるかのように結合します。
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
。
レベル: シーケンスのリスト、デフォルトは None。MultiIndex
の構築に使用する特定のレベル (一意の値)。それ以外の場合は、キーから推測されます。
Pandas がすでにこれらのレベルが何であるかを推測している場合、それを自分で指定することにどのような利点があるのでしょうか? 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
within を使用すると次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
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
。
名前: リスト、デフォルトなし
結果の階層インデックスのレベルの名前
# 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
自明なドキュメント
整合性を確認する: ブール値、デフォルトは 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]