2017-01-05 53 views
9

我正在使用代表图形的pandas 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()))真的很痛苦。如果有另一种方法可以做到这一点,那将会很好。

主要questsions是:

  • 为什么我不能用同一个.loc数组numpy的?是否因为在引擎盖下正在使用字典将多索引标签映射到位置索引?

  • 为什么列表列表给出了不同的错误?也许它真的是同样的问题,它只是采取了不同的方式?

  • 是否有另一种(理想情况下较少冗余)的方式来查找一个数据框的子集与我不知道的多索引标签的numpy数组?

+0

请注意,'df.edge_id [edge_subset2]'的作品 - 这意味着这种索引风格由于某种原因在系列而不是数据帧上受支持。奇怪的是,'df.edge_id.loc [edge_subset2]'也失败了(无缘无故,因为它没有'loc')。我建议在这里将它提交给熊猫: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在熊猫文档中很有帮助