Понимание панд многоиндексных и двойных скобок - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь понять мультииндексирование.Я нашел несколько очень хороших ссылок ( здесь от Jake VanderPlas и здесь от Nelson Minar ), но я не в состоянии понять эту концепцию.

У меня есть несколько конкретных вопросов.В частности, если мы говорим об этих данных -

import pandas as pd

# hierarchical indices and columns
index = pd.MultiIndex.from_product([[2013, 2014], [1, 2]],
                                   names=['year', 'visit'])
columns = pd.MultiIndex.from_product([['Bob', 'Guido', 'Sue'], ['HR', 'Temp']],
                                     names=['subject', 'type'])

# mock some data
data = np.round(np.random.randn(4, 6), 1)
data[:, ::2] *= 10
data += 37

# create the DataFrame
health_data = pd.DataFrame(data, index=index, columns=columns)

Тогда:

  1. Почему / как health_data.loc[:,'Guido'] удаляет индекс верхнего столбца, тогда как health_data.loc[:,['Guido']] сохраняет его.
  2. Почему health_data.loc[:, [('Bob', 'HR')]] и health_data.loc[:, ('Bob', 'HR')] работают должным образом (при условии, что ответ на вопрос 1 ясен), но health_data.loc[:, ['Bob', 'HR']] дает дополнительный столбец.
  3. Если я определю idx = pd.IndexSlice, тогда почемуhealth_data.loc[:,[idx['Bob','HR']]] возвращает предполагаемый вывод, но health_data.loc[:,list(idx['Bob','HR'])] возвращает дополнительный столбец

Поскольку мои вопросы возникли из-за моего непонимания многоиндексности, любые ссылки, которые объясняют их подробно, также будут полезны,Я видел некоторые вопросы и ответы SO (, этот немного помогает), но большинство из них очень специфичны, и я не смог найти тот, о котором вообще говорится о концепции двойных скобок.

1 Ответ

0 голосов
/ 15 мая 2018

Q1: health_data.loc[:,'Guido'] выбирает один столбец из первого уровня мультииндекса столбца, тогда как health_data.loc[:,['Guido']] выбирает список столбцов из одного и того же. Я полагаю, что разработчики Pandas могли бы сделать список из 1 элемента особым случаем и исключить избыточное измерение из ответа, но они этого не сделали.

In [6]: health_data.loc[:,'Guido']
Out[6]: 
type          HR  Temp
year visit            
2013 1      38.0  35.4
     2      29.0  36.9
2014 1      41.0  36.6
     2      26.0  36.9

In [7]: health_data.loc[:,['Guido']]
Out[7]: 
subject    Guido      
type          HR  Temp
year visit            
2013 1      38.0  35.4
     2      29.0  36.9
2014 1      41.0  36.6
     2      26.0  36.9

Q2: случаи 1 и 2 выбирают 1 столбец, сначала в виде списка из 1 элемента, а затем в качестве значения одного столбца (как в случаях 2 и 1 соответственно вашего Q1). Случай 3 более интересен: он выбирает список элементов первого уровня мультииндекса. Поскольку в значениях этих уровней существует только «Bob», он возвращает все столбцы, в которых «Bob» находится на первом уровне

In [29]: health_data.loc[:, [('Bob', 'HR')]]
Out[29]: 
subject      Bob
type          HR
year visit      
2013 1      29.0
     2      47.0
2014 1      56.0
     2      37.0

In [30]: health_data.loc[:, ('Bob', 'HR')]
Out[30]: 
year  visit
2013  1        29.0
      2        47.0
2014  1        56.0
      2        37.0
Name: (Bob, HR), dtype: float64

In [31]: health_data.loc[:, ['Bob', 'HR']]
Out[31]: 
subject      Bob      
type          HR  Temp
year visit            
2013 1      29.0  36.5
     2      47.0  37.7
2014 1      56.0  38.5
     2      37.0  37.3

Q3 это, по сути, повтор Q2: idx['Bob','HR'] оценивается как ('Bob', 'HR'), который выбирает один столбец из мультииндекса. list(idx['Bob','HR']) оценивается как ['Bob','HR'], который выбирает список столбцов с 1-го уровня мультииндекса.

In [18]: health_data.loc[:,[idx['Bob','HR']]]
Out[18]: 
subject      Bob
type          HR
year visit      
2013 1      29.0
     2      47.0
2014 1      56.0
     2      37.0

In [19]: health_data.loc[:,list(idx['Bob','HR'])]
Out[19]: 
subject      Bob      
type          HR  Temp
year visit            
2013 1      29.0  36.5
     2      47.0  37.7
2014 1      56.0  38.5
     2      37.0  37.3

Поскольку «HR» не существует на 1-м уровне мультииндекса, срез выбирает просто «Bob». Вы можете увидеть разницу более четко, если вы замените «Сью» вместо «HR»:

In [27]: health_data.loc[:,[idx['Bob','Sue']]]
Out[27]: 
subject    Bob
type       Sue
year visit    
2013 1     NaN
     2     NaN
2014 1     NaN
     2     NaN

In [28]: health_data.loc[:,list(idx['Bob','Sue'])]
Out[28]: 
subject      Bob         Sue      
type          HR  Temp    HR  Temp
year visit                        
2013 1      29.0  36.5  35.0  36.4
     2      47.0  37.7  36.0  36.4
2014 1      56.0  38.5  34.0  37.8
     2      37.0  37.3  30.0  36.9

В первом случае мы выбираем столбец со значением мультииндекса ('Bob', 'Sue'), которого не существует - следовательно, NaNs. Во втором случае мы выбираем столбцы, которые содержат все значения из списка ['Bob', 'Sue'] на первом уровне мультииндекса. Должен признаться, я застал врасплох, увидев, что кортежи и списки дают разные результаты. Опять же, я полагаю, это решение API ...

Документы покрывают большую часть этого:

https://pandas.pydata.org/pandas-docs/stable/advanced.html#advanced-indexing-with-hierarchical-index

https://pandas.pydata.org/pandas-docs/stable/advanced.html#using-slicers

...