Python 将值分配给pandas中的数据帧单元格时出现问题

Python 将值分配给pandas中的数据帧单元格时出现问题,python,pandas,indexing,Python,Pandas,Indexing,我正在组合不同的熊猫数据帧,并对最终数据帧的索引进行排序。我发现了一些对我来说毫无意义的东西。它没有给出错误,但没有真正发生赋值。下面我给出一个简单的例子 案例1: import pandas as pd ind_1 = ['a','a','b','c','c'] df_1 = pd.DataFrame(index=ind_1,columns=['col1','col2']) df_1.col1.loc['a'].iloc[0] = 1 df_1.col1.loc['b'] = 2 df_

我正在组合不同的熊猫数据帧,并对最终数据帧的索引进行排序。我发现了一些对我来说毫无意义的东西。它没有给出错误,但没有真正发生赋值。下面我给出一个简单的例子

案例1:

import pandas as pd


ind_1 = ['a','a','b','c','c']
df_1 = pd.DataFrame(index=ind_1,columns=['col1','col2'])

df_1.col1.loc['a'].iloc[0] = 1
df_1.col1.loc['b'] = 2
df_1.col1.loc['c'].iloc[0] = 3

print('Original df_1')
print(df_1)

# Original df_1
#   col1 col2
# a    1  NaN
# a  NaN  NaN
# b    2  NaN
# c    3  NaN
# c  NaN  NaN
您可以看到,此分配工作正常。但是,让我们从排序不同的索引创建数据帧

ind_1_sorted = sorted(ind_1,reverse=True)
df_1_sorted = pd.DataFrame(index=ind_1_sorted,columns=['col1','col2'])

df_1_sorted.col1.loc['a'].iloc[0] = 1
df_1_sorted.col1.loc['b'] = 2
df_1_sorted.col1.loc['c'].iloc[0] = 3

print('Sorted df_1')
print(df_1_sorted)

# Sorted df_1
#  col1 col2
# c  NaN  NaN
# c  NaN  NaN
# b    2  NaN
# a  NaN  NaN
# a  NaN  NaN
现在您可以看到,赋值只适用于非重复索引。我认为这个问题与排序有关,但让我们看看下一个案例

案例2:

ind_2 = ['c','c','b','a','a']
df_2 = pd.DataFrame(index=ind_2,columns=['col1','col2'])

df_2.col1.loc['a'].iloc[0] = 1
df_2.col1.loc['b'] = 2
df_2.col1.loc['c'].iloc[0] = 3

print('Original df_2')
print(df_2)

# Original df_2
#  col1 col2
# c  NaN  NaN
# c  NaN  NaN
# b    2  NaN
# a  NaN  NaN
# a  NaN  NaN
现在,如果不实现排序,就不会得到赋值。让我们看看如果我对索引排序会发生什么

ind_2_sorted = sorted(ind_2,reverse=False)
df_2_sorted = pd.DataFrame(index=ind_2_sorted,columns=['col1','col2'])

df_2_sorted.col1.loc['a'].iloc[0] = 1
df_2_sorted.col1.loc['b'] = 2
df_2_sorted.col1.loc['c'].iloc[0] = 3

print('Sorted df_2')
print(df_2_sorted)

# Sorted df_2
#   col1 col2
# a    1  NaN
# a  NaN  NaN
# b    2  NaN
# c    3  NaN
# c  NaN  NaN
现在,分配在排序之后工作!!我看到的唯一区别是,当索引以“标准方式”(在本例中按字母顺序)排序时,赋值就起作用了。这有什么意义吗

如果解决方案是先使用按字母顺序排序的索引,然后按照我想要的顺序进行排序,那么如何使用重复的索引进行排序,如以下示例所示


谢谢

如用户Quickbeam2k1所述,该问题是由于链分配引起的

索引对象有一个名为
get_loc
的方法,可以用来将标签转换为位置,但是它的返回类型是多态的&这就是为什么我不喜欢使用它的原因

使用数据帧索引和列上的
np.nonzero
&过滤,我们可以将标签转换为位置引用,并使用
iloc
而不是
loc
修改数据帧

i、 e.您的第一个代码示例可以重写为:

# original
df_1.col1.loc['a'].iloc[0] = 1
df_1.col1.loc['b'] = 2
df_1.col1.loc['c'].iloc[0] = 3

# works for all indices
col1_mask = df_1.columns == 'col1'
a_mask, = np.nonzero(df_1.index == 'a')
b_mask, = np.nonzero(df_1.index == 'b')
c_mask, = np.nonzero(df_1.index == 'c')
df_1.iloc[a_mask[0], col1_mask] = 1
df_1.iloc[b_mask, col1_mask] = 1
df_1.iloc[c_mask[0], col1_mask] = 3

类似地,对于其他示例

我认为,这与链式赋值问题有关,您根本无法通过CopyWarning获得
设置。检查一下。简而言之:您不应该像现在这样设置元素;)我同意@Quickbeam2k1。Pandas documenation解释说,在没有错误或警告的情况下,链式索引可能会导致赋值失败。这是因为您可以为原始数据的副本赋值,这是绝对合法的,但不是您想要的(就像可变与不可变数据类型一样)。我想这不是一个bug,而是Python的特性。因此,请注意熊猫中的链接索引。另外,始终使用
.loc/.at
语法进行索引可能是一个好习惯。@Quickbeam2k1非常准确地识别了这里的问题,谢谢。