我正在使用代表图表的pandas DataFrame。数据帧由指示节点端点的MultiIndex索引。
设定:
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()))
真的很痛苦。如果有另一种方法可以做到这一点会很好。
主要任务是:
为什么我不能使用.loc
的numpy数组?是因为在引擎盖下使用字典将多索引标签映射到位置索引?
为什么列表清单会出现不同的错误?也许它真的是同样的问题,只是采取了不同的方式?
是否有另一种(理想情况下更简洁)的方法来查找数据帧的子集,其中包含我不知道的多索引标签数组?
答案 0 :(得分:2)
字典键是不可变的,这基本上就是为什么你不能使用列表列表来访问多索引。
为了能够使用loc
访问多索引数据,您需要将numpy
数组转换为元组列表;元组是不可变的,一种方法是使用map
,如你所提到的那样
如果您想避免使用地图,并且您正在从csv文件读取边缘,则可以将它们读入数据框,然后使用to_records
属性设置为index
{ {1}},
另一种方法是通过从False
创建一个多索引,但你必须在传递之前转置列表,以便每个级别是数组中的一个列表
ndarray
我发现pandas文档中的文章advanced multi-indexing非常有用