代入するとき、との間には非常に大きな違いがseries.iloc[:]
ありseries[:]
ます。(i)loc
常に、割り当て元が割り当て対象のインデックスと一致することを確認します。一方、[:]
構文は、インデックスのアライメントをバイパスして、基になるNumPy配列に割り当てます。
s = pd.Series(index=[0, 1, 2, 3], dtype='float')
s
0 NaN
1 NaN
2 NaN
3 NaN
dtype: float64
# Let's get a reference to the underlying array with `copy=False`
arr = s.to_numpy(copy=False)
arr
# array([nan, nan, nan, nan])
# Reassign using slicing syntax
s[:] = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
s
0 1
1 2
2 3
3 4
dtype: int64
arr
# array([1., 2., 3., 4.]) # underlying array has changed
# Now, reassign again with `iloc`
s.iloc[:] = pd.Series([5, 6, 7, 8], index=[3, 4, 5, 6])
s
0 NaN
1 NaN
2 NaN
3 5.0
dtype: float64
arr
# array([1., 2., 3., 4.]) # `iloc` created a new array for the series
# during reassignment leaving this unchanged
s.to_numpy(copy=False) # the new underlying array, for reference
# array([nan, nan, nan, 5.])
違いを理解したところで、コードで何が起こるか見てみましょう。ループのRHSを印刷して、何を割り当てているかを確認します。
for i in range(2):
print(a_df.iloc[0, i*4:(i+1)*4])
# output - first row
0 1
1 2
2 3
3 4
Name: 0, dtype: int64
# second row. Notice the index is different
4 5
5 6
6 7
7 8
Name: 0, dtype: int64
b_df.iloc[i, :]
2番目の反復でに割り当てる場合、インデックスが異なるため、何も割り当てられず、NaNのみが表示されます。ただし、に変更 b_df.iloc[i, :]
するb_df.iloc[i][:]
と、基になるNumPy配列に割り当てられるため、インデックスの配置はバイパスされます。この操作は次のように表現されます
for i in range(2):
b_df.iloc[i, :] = a_df.iloc[0, i*4:(i+1)*4].to_numpy()
b_df
0 1 2 3
0 1 2 3 4
1 5 6 7 8
また、これが連鎖代入の一種であることもお勧めします。これは良いことではなく、コードが読みにくくなり、理解しにくくなります。
b_df.iloc[1] = a_df.iloc[0, 4:8]
indexのシリーズをindexのシリーズに割り当て[4, 5, 6, 7]
ます[0, 1, 2, 3]
。重複がないためNaN
、すべての要素に割り当てられます。この時点まで、私には理にかなっています。しかし、あなたのように、なぜb_df.iloc[1][:] = ...
動作が異なるのかははっきりしません。オブジェクトb_df.iloc[1]
を検査しb_df.iloc[1][:]
、インデックスの違いを明らかにしません。私の推測では、コピー([:]
)に直接割り当てることは、Pandasによって特別なケースとして扱われるため、割り当て先のインデックスが無視され、この矛盾が生じます。