Как установить значения для данного уровня индекса в панде DataFrame - PullRequest
0 голосов
/ 29 ноября 2018

Я пытаюсь установить все значения столбца в многоиндексированном панде 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

Ошибка совершенно очевидна, поскольку я нигде не указываю, для какого уровня данные должныбыть.Например, если бы у меня был другой «случай», длины данных было бы недостаточно, чтобы определить, что я имею в виду с последней строкой кода выше.

Что мне, очевидно, нужно сделать, это сказать parameters, чтоДанные, которые я передаю, предназначены для уровня индекса «Время».Однако все попытки, которые я обнаружил с помощью loc -индексирования, приводят к:

  • другим фреймам данных или сериям с полной длиной или
  • требуют указания отдельных сценариев

В настоящее время я делаю следующее:

for c in parameters.index.levels[0]:
    parameters.loc[(c, slice(None)), 'CaseInvariantTimeVariant'] = 1, 2, 3

, что приводит к:

enter image description here

Хотя это делает то, чтоЯ хочу, чтобы он чувствовал себя неудовлетворительно по двум причинам:

  • ему нужны две довольно загадочные строки, чтобы сделать что-то, казалось бы, простое: (Установите все значения для Time, используя эту итерацию, которую я вам даю!)
  • мы должны явно выполнять итерации по всем уровням индекса, которые обрабатываются одинаково, так что это не обобщает более чем на два уровня

Кажется, что 'groupby' может быть полезнымздесь, но до сих пор я не смог составить большую часть документации.

1 Ответ

0 голосов
/ 29 ноября 2018

Если мы всегда хотим выровнять последовательность по самому внутреннему уровню, мы могли бы:

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

* Обратите внимание, что нам все еще нужно sort индекс перед назначением последовательности: 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))

Если вы хотите функциюкоторый всегда повторяет последовательность по уровню nth в индексе:

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))
...