分配回来时,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, :]
在第二次迭代中分配给时,索引是不同的,因此未分配任何内容,您只会看到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]
将具有索引[4, 5, 6, 7]
的序列分配给具有索引的序列[0, 1, 2, 3]
。没有重叠,因此将NaN
s分配给所有元素。到目前为止,这对我来说很有意义。但是,像您一样,我不清楚为什么b_df.iloc[1][:] = ...
行为会有所不同-检查对象b_df.iloc[1]
并b_df.iloc[1][:]
发现索引之间没有差异。我最好的猜测是,直接分配给副本([:]
)被Pandas视为特殊情况,这使其忽略了受让人的索引并造成了这种差异。