Есть ли функция для уменьшения MultiIndex? - PullRequest
0 голосов
/ 15 ноября 2018

Предположим, у меня есть DataFrame, который выглядит как:

import pandas as pd
import numpy as np

df = pd.DataFrame({'Week' : [1, 2, 1, 2, 1, 2, 1, 2],
                           'Rabbits' : np.random.randn(8),
                           'Donkeys' : np.random.randn(8) * 4,
                           'Mice'   :  np.random.randn(8) * 4})

, что делает df:

Example df

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

week_group = df.groupby('Week')
week_group = week_group[df.columns.difference(["Week"])]
week_cor = week_group.corr()

, что составляет week_cor a MultiIndex для 1-й недели и 2-й недели:

Donkey MultiIndex

Итак, теперь я хочу сделать следующее: я хочу создать DataFrame на основе "двух" DataFrame с.Для уточнения: давайте рассматривать неделю 1 как df1, а неделю 2 как df2.Теперь давайте рассмотрим запись в df1 entry1 и запись в df2, entry2.Получившийся DataFrame построен следующим образом:

def collapse(entry1, entry2):
    if abs(entry1) >= 0.6 and abs(entry2) >= 0.6:
        return 1
    else:
        return 0

Так что в этом случае я бы хотел что-то вроде:

         Donkeys   Mice      Rabbits                              
Donkeys  1.000000  0.000000  0.000000
Mice     0.000000  1.000000  0.000000
Rabbits  0.000000  0.000000  1.000000

В Python я обычно выполняю reduce вложенныйсписок, но он не работает:

from functools import reduce

def collapse(entry1, entry2):
    if abs(entry1) >= 0.6 and abs(entry2) >= 0.6:
        return 1
    else:
        return 0

reduce(collapse, week_cor)

Что дает:

TypeError: bad operand type for abs(): 'str'

Что имеет смысл, поскольку это своего рода массив со строковыми ключами.

Я мог бы неправильно понять цель pandas, но мне кажется, что идея выполнения операции reduce вдоль MultiIndex была бы довольно распространенной, и что pandas мог бы сделать это.Пожалуйста, исправьте меня, если я ошибаюсь в этом предположении, и если нет, то каков стандартный способ сокращения по MultiIndex?

В целом: я беру один DataFrame и группирую данные покакой-то момент времени.Затем я выполняю операцию (в этом примере corr), чтобы получить MultiIndex на основе времени.Я хочу «свернуть» или уменьшить MultiIndex таким же образом, как reduce список в Python.В результате я уменьшаю MultiIndex до DataFrame.

Ответы [ 3 ]

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

Примечание : я опубликовал этот ответ до того, как увидел комментарий Ben.T, его путь более лаконичен и, вероятно, его следует использовать.

Я расширяю ответ Даскьенца, чтобы сделать его более общим:

Как сказал Даскиенц:

Так что я думаю, что самое простое решение для того, что вы хотите, это удалить MultiIndex, используя pandas.DataFrame.reset_index

Таким образом, от:

animal_group = week_cor.reset_index()

Получаем:

Reset Index

Затем можно снова сгруппировать по "level_1", чтобы проиллюстрировать (фрагмент того, как это выглядит):

animal_group = week_cor.reset_index().groupby("level_1")
animal_group.get_group("Donkeys")

дает:

Donkey Slice

Это можно уменьшить с помощью agg (хотя я не уверен, что это лучший вариант), и столбец "Week" можно просто удалить в конце:

from math import floor

def collapse(x):
    x = x.map(lambda elem: 1 if abs(elem) > 0.6 else 0)
    # A little bit of a math trick here...
    return floor(x.abs().sum() / 2)

animal_group.agg(collapse).drop("Week", axis=1)

Все еще кажется немного многословным (или, возможно, я ожидаю слишком многого от Python). Но в итоге:

Animal Time Cor

По желанию.

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

В этом случае, я думаю, вы можете просто сделать еще один groupby на первом уровне week_cor, проверяя, все ли значения абс больше или равны 0,6

print(week_cor)

               Donkeys      Mice   Rabbits
Week                                      
1    Donkeys  1.000000 -0.118953 -0.235307
     Mice    -0.118953  1.000000  0.803987
     Rabbits -0.235307  0.803987  1.000000
2    Donkeys  1.000000  0.229929 -0.593603
     Mice     0.229929  1.000000 -0.645369
     Rabbits -0.593603 -0.645369  1.000000

Код:

week_cor.groupby(level=1).apply(lambda x: x.abs().ge(0.6).all())  

         Donkeys   Mice  Rabbits
Donkeys     True  False    False
Mice       False   True     True
Rabbits    False   True     True
0 голосов
/ 15 ноября 2018

Так что я думаю, что самое простое решение для того, что вы хотите - это сбросить MultiIndex, используя pandas.DataFrame.reset_index, например, так:

week_cor = week_cor.reset_index() 

Теперь вы можете выбрать подходящее подмножество корреляции в столбце Week. Таким образом, вы можете легко выполнять дальнейшие операции над ними двумя. Вот решение numpy, которое вы могли бы использовать.

cols = ['Donkeys','Mice','Rabbits']
df1 = week_cor[week_cor['Week'] == 1][cols].values #ndarray
df2 = week_cor[week_cor['Week'] == 2][cols].values #ndarray

def collapse(A, B):
    return np.where((A >= 0.6) & (B >= 0.6), 1, 0)

new_df = pd.DataFrame(collapse(df1, df2), index=cols, columns=cols)

Дайте мне знать, если вы заставите reduce работать, потому что мне было бы интересно узнать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...