Переиндексирование мультииндексных фреймов данных в Pandas - PullRequest
0 голосов
/ 09 октября 2018

Я пытаюсь переиндексировать один мультииндексный фрейм данных на основе другого мультииндексного фрейма данных.Для dfs с одиночным индексированием это работает:

index1 = range(3, 7)
index2 = range(1, 11)
values = [np.random.random() for x in index1]

df = pd.DataFrame(values, index=index1, columns=["values"])

print(df)
print(df.reindex(index2, fill_value=0))

Вывод:

     values
3  0.458003
4  0.945828
5  0.783369
6  0.784599
      values
1   0.000000
2   0.000000
3   0.458003
4   0.945828
5   0.783369
6   0.784599
7   0.000000
8   0.000000
9   0.000000
10  0.000000

Добавляются новые строки на основе index2, и значение для y устанавливается равным0.Это то, что я ожидаю.

Теперь давайте попробуем нечто похожее для многоиндексного df:

data_dict = {
    "scan": 1,
    "x": [2,3,5,7,8,9],
    "y": [np.random.random() for x in range(1,7)]
}

index1 = ["scan", "x"]
df = pd.DataFrame.from_dict(data_dict).set_index(index)
print(df)

index2 = list(range(4, 13))
print(df.reindex(index2, level="x").fillna(0))

Вывод:

               y
scan x          
1    2  0.771531
     3  0.451761
     5  0.434075
     7  0.135785
     8  0.309137
     9  0.838330
               y
scan x          
1    5  0.434075
     7  0.135785
     8  0.309137
     9  0.838330

Что дает?Вывод отличается от ввода: первые два значения были удалены.Но другие значения - промежуточные (например, 4) или больше (например, 10 или выше) - отсутствуют.Чего мне не хватает?

Реальные фреймы данных имеют 6 уровней индекса и десятки или сотни строк, но я думаю, что этот код решает проблему.Я потратил немного времени на просмотр df.realign, df.join и много времени прочесывал SO, но я не нашел решения.Извините, если это дубликат!

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

Опираясь на обходной путь @ Сергея, вот что я закончил.Я расширил пример, чтобы иметь больше уровней, точнее копируя мои собственные данные.

Создайте df:

data_dict = {
    "sample": "A", 
    "scan": 1,
    "meas_time": datetime.now(),
    "x": [2,3,5,7,8,9],
    "y": [np.random.random() for x in range(1,7)]
}

index1 = ["sample", "scan", "meas_time", "x"]
df = pd.DataFrame.from_dict(data_dict).set_index(index1)
print(df)

Попробуйте переиндексировать:

index2 = range(4, 13)
print(df.reindex(labels=index2, level="x").fillna(0))

Реализация СергеяОбходной путь:

df.reindex(
    pd.MultiIndex.from_product(
        [df.index.get_level_values("sample").unique(),
         df.index.get_level_values("scan").unique(),
         df.index.get_level_values("meas_time").unique(),
         index2], 
        names=["sample", "scan", "meas_time", "x"])
    ).fillna(0)

Примечания: если не включить .unique(), для каждого уровня вычисляется кратное (продукт?!?) кадра данных.Вероятно, поэтому мое ядро ​​и раньше падалоЯ не включал .unique().

Это кажется странным pandas поведением.Я также нашел обходной путь, который включал цепочку .reset_index().set_index("x").reindex("blah").set_index([list]).Мне бы очень хотелось знать, почему переиндексация такова.

0 голосов
/ 09 октября 2018

Позвольте мне предложить обходной путь:

print(df.reindex(pd.MultiIndex.from_product([df.index.get_level_values(0).unique(), index2], names=['scan', 'x'])).fillna(0))
                y
scan x           
1    4   0.000000
     5   0.718190
     6   0.000000
     7   0.612991
     8   0.609323
     9   0.991806
     10  0.000000
     11  0.000000
     12  0.000000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...