我正在尝试设置多索引 pandas DataFrame 中列的所有值,仅指定单个索引级别的数据。 到目前为止我提出的解决方案并不令人满意,但这可能最好用代码来解释:
from pandas import MultiIndex, DataFrame
idx = MultiIndex.from_product([['A', 'B'], [1, 2, 3]],
names=['Cases', 'Time'])
parameters = DataFrame(index=idx)
parameters['CaseAndTimeInvariant'] = 1
parameters['CaseAndTimeVariant'] = 1, 2, 3, 4, 5, 6
# Set the values in 'Time' for all cases to 1, 2, 3
parameters['CaseInvariantTimeVariant'] = 1, 2, 3
# ValueError: Length of values does not match length of index
这个错误非常明显,因为我没有在任何地方指定数据应该属于哪个级别。如果我有例如另一种“情况”,数据的长度不足以确定我上面最后一行代码的含义。
我显然需要做的是告诉参数
我传递的数据是针对“时间”索引级别的。然而,我发现的所有使用 loc
索引的尝试都会导致:
- 具有完整长度的其他数据帧或系列
- 需要具体场景的说明
目前我正在执行以下操作:
for c in parameters.index.levels[0]:
parameters.loc[(c, slice(None)), 'CaseInvariantTimeVariant'] = 1, 2, 3
结果:
虽然这达到了我想要的目的,但在两个方面让人感到不满意:
- 它需要两行相当神秘的代码来完成一些看似简单的事情:
(使用我给您的这个可迭代对象设置
Time
的所有值!) - 我们需要显式迭代所有被同等对待的索引级别,因此这不能很好地推广到两个以上的级别
看起来“groupby”在这里可能会有所帮助,但直到现在我还没有能够了解很多文档。
最佳答案
如果我们总是想将序列与最内层对齐,我们可以:
sequence = [1, 2, 3]
inner_level = parameters.index.get_level_values(len(parameters.index.levels) - 1)
n = inner_level.size // inner_level.nunique()
parameters['CaseInvariantTimeVariant'] = sequence * n
*请注意,在分配序列之前我们仍然需要对索引进行排序
:parameters.sort_index(inplace=True)
。
如果我们想使用外部级别,请执行以下操作:
我会sort_index
,然后重复该序列n
次,其中n
是唯一索引的长度(Cases
在您的数据中)。
parameters.sort_index(inplace=True)
my_sequence = (1, 2, 3)
# below by level: parameters.index.get_level_values(0).nunique()
n = parameters.index.get_level_values('Cases').nunique()
parameters['CaseInvariantTimeVariant'] = my_sequence * n
如果您想要一个始终按最外层索引重复序列的函数:
def repeat_seq_by_outer_index(index, sequence):
return sequence * index.get_level_values(0).nunique()
repeat_seq_by_outer_index(parameters.index, (1, 2, 3))
如果您想要一个始终按索引中的第 n 层重复序列的函数:
def repeat_seq_by_nth_index(index, level, sequence):
return sequence * index.get_level_values(level).nunique()
repeat_seq_by_nth_index(parameters.index, 0, (1, 2, 3))
关于python - 如何在 pandas DataFrame 中设置给定索引级别的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53534170/