如何正确使用包含间隔的多索引Pandas数据帧?

2024-05-28 23:29:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图分割一个数据帧,它有一个由IntervalIndex和一个常规索引组成的多重索引。示例代码:

from pandas import Interval as ntv

df = pd.DataFrame.from_records([
   {'id': 1, 'var1': 0.1, 'ntv': ntv(0,10), 'E': 1}, 
   {'id':2, 'var1': 0.5, 'ntv': ntv(0,12), 'E': 0}
], index=('ntv', 'id'))

看起来像这样:

^{pr2}$

我想做的是在特定值处对数据帧进行切片,并返回具有包含该值的间隔的所有行。例如:

df.loc[4]

应该回来(平凡地)

    E  var1
id
1   1   0.1
2   0   0.5

问题是我一直得到一个关于索引的TypeError,而{a1}显示了一个类似的操作(但是在一个级别的索引上),它确实产生了我要查找的内容。在

TypeError: only integer scalar arrays can be converted to a scalar index

我试过很多东西,似乎都没什么正常的。我可以在dataframe中包含id列,但是我宁愿保持索引的唯一性,而且我会不断地调用set_index('id')。在

我觉得要么a)我遗漏了关于MultiIndex的一些东西,要么b)在MultiIndex中使用IntervalIndex有一个错误/歧义。在


Tags: 数据代码fromid示例pandasdfindex
3条回答

因为我们说的是间隔,所以有一个称为get_loc的方法来查找在间隔之间有值的行。我的意思是:

from pandas import Interval as ntv

df = pd.DataFrame.from_records([
   {'id': 1, 'var1': 0.1, 'ntv': ntv(0,10), 'E': 1}, 
   {'id':2, 'var1': 0.5, 'ntv': ntv(0,12), 'E': 0}
], index=('ntv', 'id'))

df.iloc[(df.index.get_level_values(0).get_loc(4))]
            E  var1
ntv     id         
(0, 10] 1   1   0.1
(0, 12] 2   0   0.5

df.iloc[(df.index.get_level_values(0).get_loc(11))]
             E  var1
ntv     id         
(0, 12] 2   0   0.5

如果一个interval有多行数据,也可以这样做,即

^{pr2}$

如果用列表理解来计时,这种方法对于大型数据帧(即

ndf = pd.concat([df]*10000)

%%timeit
ndf.iloc[ndf.index.get_level_values(0).get_loc(4)]
10 loops, best of 3: 32.8 ms per loop

%%timeit
intervals = ndf.index.get_level_values(0)
mask = [4 in i for i in intervals]
ndf.loc[mask]
1 loop, best of 3: 193 ms per loop

所以我做了一点挖掘,试图理解这个问题。如果我尝试运行你的代码,会发生以下情况。 您尝试用索引到索引标签中 切片(数组([0,1],dtype=int64),数组([1,2],dtype=int64),无

(当我说index_type时,我指的是Pandas数据类型)

索引类型的标签是映射到索引类型的levels数组的索引列表。下面是文档中的一个示例。在

   >>> arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']]
    >>> pd.MultiIndex.from_arrays(arrays, names=('number', 'color'))
    MultiIndex(levels=[[1, 2], ['blue', 'red']],
           labels=[[0, 0, 1, 1], [1, 0, 1, 0]],
           names=['number', 'color'])

请注意标签中的第二个列表是如何连接到级别顺序的。等级[1][1]等于红色,[1][0]等于蓝色。在

总之,这一切都是在说,我不相信intervalindex是用来重叠使用的。如果你看看最初的提议 https://github.com/pandas-dev/pandas/issues/7640

“IntervalIndex将是一个单调且不重叠的一维区间数组。”

我的建议是把间隔时间移到列中。您可以用numba编写一个简单的函数来测试每个区间是否有一个数字。你介意解释一下你从这段时间中获益的方式吗?在

这并不是一个真正的解决方案,我也不完全理解,但我认为这可能与你的区间指数不是单调的有关(因为你有重叠的区间)。我想这在某种意义上可以被认为是单调的,所以也许你可以说重叠意味着索引不是唯一的?在

总之,看看这个github问题:

ENH: Implement MultiIndex.is_monotonic_decreasing #17455

下面是一个数据示例,但将间隔更改为非重叠(0,6)&;(7,12):

df = pd.DataFrame.from_records([
   {'id': 1, 'var1': 0.1, 'ntv': ntv(0, 6), 'E': 1}, 
   {'id': 2, 'var1': 0.5, 'ntv': ntv(7,12), 'E': 0}
], index=('ntv', 'id'))

现在,loc工作正常:

^{pr2}$

相关问题 更多 >

    热门问题