Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何正确使用包含间隔的多索引的熊猫数据帧?_Python_Pandas_Dataframe - Fatal编程技术网

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

Python 如何正确使用包含间隔的多索引的熊猫数据帧?,python,pandas,dataframe,Python,Pandas,Dataframe,我正在尝试将数据分割成一个数据帧,该数据帧有一个由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', '

我正在尝试将数据分割成一个数据帧,该数据帧有一个由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'))
看起来像这样:

            E  var1
ntv     id
(0, 10] 1   1   0.1
(0, 12] 2   0   0.5
我想做的是在数据帧中以特定的值进行切片,并返回具有包含该值的间隔的所有行。例:

df.loc[4]
应该返回(琐碎地)

问题是我不断得到一个关于索引的
TypeError
,并且显示了一个类似的操作(但是在一个级别索引上),它确实生成了我要查找的内容

TypeError: only integer scalar arrays can be converted to a scalar index
我试过很多东西,但似乎没有什么能正常工作。我可以在数据框中包含
id
列,但我宁愿保持索引的唯一性,并且我会不断调用
set\u index('id')


我觉得要么a)我缺少了关于多索引的一些信息,要么b)在多索引中使用IntervalIndex存在错误/歧义

借助@Dark's,
Index.get\u loc
只需调用
Index.get\u indexer
,因此在没有额外参数和繁文缛节的情况下调用底层方法可能更有效

idx = df.index.get_level_values(0)
df.iloc[idx.get_indexer([4])]
我最初提出的解决方案是:

intervals = df.index.get_level_values(0)
mask = [4 in i for i in intervals]
df.loc[mask]
不管怎样,这当然很奇怪,虽然它们返回两个不同的结果,但看起来确实与索引是唯一的/单调的/两者都不是有关:

df.reset_index(level=1, drop=True).loc[4] # good
df.loc[4]  # TypeError

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

无论如何,请查看此github问题:

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

现在,
loc
工作正常:

df.loc[4]

    E  var1
id         
1   1   0.1

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

(当我说索引类型时,我指的是数据类型)

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

   >>> 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是以重叠的方式使用的。如果你看一下最初的提案

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


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

因为我们讲的是间隔,所以有一种叫做
get\u 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
如果一个区间有多行数据,也可以这样做,即

df = pd.DataFrame.from_records([
   {'id': 1, 'var1': 0.1, 'ntv': ntv(0,10), 'E': 1}, 
   {'id': 3, '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
        3   1   0.1
(0, 12] 2   0   0.5
如果您通过列表理解来完成这一点,那么对于大型数据帧(即

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
如果要删除索引级别,可以添加

a.index = a.droplevel(0)

呵呵。非常有趣的是,它适用于不重叠的间隔。这给了我一些开始。这个答案上的+1,尽管我注意到,
get_loc
只是
get_indexer
在引擎盖下烘焙了一些参数in@BradSolomon我的第一个想法是
get\u indexer
,它比Jeff core developer曾经建议的
get_loc
要长一点,所以我选择了它。当然,它是随着时间的推移跟踪用户,也就是说,给定一组时间,确定个人处于什么状态(虽然不是所有人每次都可用)。这是一个时变回归。你有没有考虑过一个布尔矩阵,其中列是时间戳,用户是索引?我们在这里讨论了多少用户和时间戳?可能是任意的:数千个用户(或更多)和数百个时间戳?老实说,您应该使用一个普通的数据帧,用户作为索引,时间戳作为列。对于这么小的数据集,您不会遇到内存问题。即使这样做,也可以通过将数据帧转换为int8或bool来节省大量空间。当然,这是假设您只跟踪登录。
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
def check_value(num):
    return df[[num in i for i in map(lambda x: x[0], df.index)]] 

a = check_value(4)
a
>> 
            E  var1
ntv     id         
(0, 10] 1   1   0.1
(0, 12] 2   0   0.5  
a.index = a.droplevel(0)