我正在组合不同的熊猫数据框,并对最终数据框的索引进行排序,我发现有些东西对我没有任何意义。它没有错误,但实际上没有分配。我在下面给出一个简化的例子
情况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
现在,分配工作在排序后生效!!我看到的唯一区别是,当索引以“标准方式”(在这种情况下按字母顺序)排序时,赋值有效。有什么意义吗?
如果解决方案是先使用按字母顺序排序的索引,然后按所需顺序对其进行排序,那么如何像这些示例中那样使用重复索引进行排序?
谢谢!
答案 0 :(得分:2)
正如Quickbeam2k1用户所说,问题是由于链分配引起的。
索引对象具有一种称为get_loc
的方法,可用于将标签转换为位置,但是它的返回类型是多态的,这就是为什么我不喜欢使用它的原因。
使用np.nonzero
并过滤数据框的索引和列,我们可以将标签转换为位置引用,并使用iloc
而不是loc
即您的第一个代码示例可以重写为:
# 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
与其他示例类似