2017-01-05 4 views
9

Я работаю с пандами DataFrame, которые представляют собой график. Фрейм данных индексируется с помощью MultiIndex, который указывает конечные точки узла.Поиск Pandas MultiIndex с массивами Numpy

Установка:

import pandas as pd 
import numpy as np 
import itertools as it 
edges = list(it.combinations([1, 2, 3, 4], 2)) 

# Define a dataframe to represent a graph 
index = pd.MultiIndex.from_tuples(edges, names=['u', 'v']) 
df = pd.DataFrame.from_dict({ 
    'edge_id': list(range(len(edges))), 
    'edge_weight': np.random.RandomState(0).rand(len(edges)), 
}) 
df.index = index 
print(df) 
## -- End pasted text -- 
    edge_id edge_weight 
u v      
1 2  0  0.5488 
    3  1  0.7152 
    4  2  0.6028 
2 3  3  0.5449 
    4  4  0.4237 
3 4  5  0.6459 

Я хочу, чтобы иметь возможность индексировать в график, используя ребро подмножество, поэтому я решил использовать MultiIndex. Я могу сделать это просто отлично, пока входной файл df.loc - это список кортежей.

# Select subset of graph using list-of-tuple indexing 
edge_subset1 = [edges[x] for x in [0, 3, 2]] 
df.loc[edge_subset1] 
## -- End pasted text -- 
    edge_id edge_weight 
u v      
1 2  0  0.5488 
2 3  3  0.5449 
1 4  2  0.6028 

Однако, когда мой список ребер является NumPy массив (как это часто бывает), или список списков, то я, кажется, не в состоянии использовать df.loc свойство.

# Why can't I do this if `edge_subset2` is a numpy array? 
edge_subset2 = np.array(edge_subset1) 
df.loc[edge_subset2] 
## -- End pasted text -- 
TypeError: unhashable type: 'numpy.ndarray' 

Было бы хорошо, если бы я мог просто все arr.tolist(), но это приводит к кажущейся различной ошибки.

# Why can't I do this if `edge_subset2` is a numpy array? 
# or if `edge_subset3` is a list-of-lists? 
edge_subset3 = edge_subset2.tolist() 
df.loc[edge_subset3] 
## -- End pasted text -- 
TypeError: '[1, 2]' is an invalid key 

Это реальная боль, чтобы использовать list(map(tuple, arr.tolist())) каждый раз, когда я хочу, чтобы выбрать подмножество. Было бы неплохо, если бы был другой способ сделать это.

Основные ярлыков являются:

  • Почему я не могу использовать Numpy массива с .loc? Это потому, что под капотом используется словарь для сопоставления мультииндексных меток с позиционными индексами?

  • Почему список списков дает другую ошибку? Может быть, это действительно та же самая проблема, что ее просто поймали по-другому?

  • Есть ли другой (в идеале менее подробный) способ подмножества подмножества данных с множеством многозначных меток с несколькими индексами, о которых я не знаю?

+0

Обратите внимание, что 'df.edge_id [edge_subset2]' работает - это означает, что этот стиль индексирования по какой-либо причине поддерживается в серии, но не в DataFrame. Как ни странно, 'df.edge_id.loc [edge_subset2]' тоже не работает (без причины, поскольку он работает без 'loc'). Я предлагаю передать это Pandas здесь: https://github.com/pandas-dev/pandas/issues –

ответ

2

Клавиши словаря неизменяемы, поэтому вы не можете использовать список списков для доступа к мультииндексу.

Для доступа к данным с несколькими индексами с использованием loc вам необходимо преобразовать массив numpy в список кортежей; кортежи неизменны, один из способов сделать это является использование map, как вы упомянули

Если вы хотите, чтобы избежать использования карты и вы читаете края образуют файл CSV, вы можете прочитать их в кадр данных, а затем использовать to_records с атрибут index установлен False, Другим способом может быть путем создания мульти-индекс от ndarray, но вы должны перенести список, прежде чем передать его так, чтобы каждый уровень один список в массиве

import pandas as pd 

df1 = df.loc[pd.MultiIndex.from_arrays(edge_subset2.T)] 


print(df1) 

#outputs 
      edge_id edge_weight 
------ --------- ------------- 
(1, 2)   0  0.548814 
(2, 3)   3  0.544883 
(1, 4)   2  0.602763 

я нашел статья advanced multi-indexing в документации pandas очень полезна

Смежные вопросы