loc 和 iloc 方法在分配时的行为是否不同?

Do loc and iloc methods behave differently in assignment?

我需要根据另一个数据框中的 ID 将新列添加到数据框中。

我创建了一小段我正在尝试做的事情:

import pandas as pd
import numpy as np

a = pd.DataFrame([['ass-123-43', ['123', '456']],['ass-123-44', ['123', '457']]], columns=['customer_id', 'order_id']) 
b = pd.DataFrame([['ass-123-43'], ['ass-123-44']], columns=['customer_id'])

dict_a = a.set_index('customer_id').order_id.to_dict()

b['order_id'] = np.nan

for customer_id, order_id in dict_a.items():
    if customer_id in b.customer_id.values:
        b.iloc[b.customer_id == customer_id, 1] = pd.Series([order_id])

print(b)

当我使用 iloc 方法时,代码按预期工作:

  customer_id    order_id
0  ass-123-43  [123, 456]
1  ass-123-44  [123, 457]

但是当我使用 loc 方法时它没有按预期工作:

import pandas as pd
import numpy as np

a = pd.DataFrame([['ass-123-43', ['123', '456']],['ass-123-44', ['123', '457']]], columns=['customer_id', 'order_id'])
b = pd.DataFrame([['ass-123-43'], ['ass-123-44']], columns=['customer_id'])

dict_a = a.set_index('customer_id').order_id.to_dict()

b['order_id'] = np.nan

for customer_id, order_id in dict_a.items():
    if customer_id in b.customer_id.values:
        b.loc[b.customer_id == customer_id, 'order_id'] = pd.Series([order_id])

print(b)

我得到了这个结果:

  customer_id    order_id
0  ass-123-43  [123, 456]
1  ass-123-44         NaN

除了 loc 使用标签分配行和 iloc 一个数字之外,还有什么我错过的吗?

您可以详细了解 .iloc.loc 之间的差异,但对于您的特定情况,您得到 NaN 的原因是 你要分配什么。使用 .iloc,它完全忽略了您分配的值的 index(即 pd.Series([order_id])),因此它工作正常并且不会产生 NaN .

然而,对于 .loc,它 尊重索引。在您的示例中,pd.Series([order_id]) 的索引为 [0],如您所见:

>>> order_id = '123'
>>> pd.Series([order_id])
0    123
dtype: object

现在查看出现 NaN 的行的索引。是 1。但是您尝试分配给它的值的索引是 0,如上所示。 索引不匹配! 发生了什么?缺失值 - NaN.


如果您想要使用.loc而不是.iloc,您可以通过将 Series 对象转换为 numpy 来避免这个 mismatched-index 问题分配前的数组(使用 .to_numpy()):

b.loc[b.customer_id == customer_id, 'order_id'] = pd.Series([order_id]).to_numpy()

这将按预期工作。