给定数据框中的pd.Interval列,则对落在Interval范围内的值进行过滤

时间:2019-08-30 01:19:35

标签: python pandas dataframe

我想为数据帧中的每一行分配一个间隔,以使所有行都不会重叠,并且将覆盖整个可能的范围。因此,我可以根据给定时间间隔内的值过滤行。

我使用过pd.Interval,但是当我尝试“正常”过滤时,它不起作用:

df = pd.DataFrame({"rating":["bad","average","good"],
                   "stars":[pd.Interval(left=0,right=2,closed="left"),
                            pd.Interval(left=2,right=4,closed="left"),
                            pd.Interval(left=4,right=5,closed="both")]})
stars_val=2.5
filtered_df = df[stars_val in df.stars]

它给出了以下错误:

KeyError                                  Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
   2656             try:
-> 2657                 return self._engine.get_loc(key)
   2658             except KeyError:

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: False

有效代码应给出结果:

    rating   stars
1  average  [2, 4)

3 个答案:

答案 0 :(得分:1)

您可以使用它:

filtered=[]
for i in df.index:   
    filtered.append(stars_val in df.stars[i])
filtered_df=df[filtered]

输出:

    rating  stars
1   average [2, 4)

说明:

stars_val in df.stars

输出:

False

请记住,您需要一个布尔值列表来过滤df, 执行我的代码后,您将获得:

filtered

输出:

[False, True, False]

df[filtered]之所以有效,是因为列表的长度与数据框的列的长度匹配

答案 1 :(得分:1)

df.stars是一个系列。您要检查stars_val是否在系列的每个间隔中

filtered_df = df[[stars_val in x for x in df.stars]]

    rating   stars
1  average  [2, 4)

答案 2 :(得分:1)

如果您所有的间隔都具有相同的closed,则您的列将以IntervalArray为后盾,并且您可以将IntervalArray.contains方法用于矢量化实现:

In [2]: np.random.seed(123)

In [3]: start = np.random.randint(100, size=1000)

In [4]: ia = pd.arrays.IntervalArray.from_arrays(start, start + 5)

In [5]: df = pd.DataFrame({'A': list('abcde') * 200, 'B': ia})

In [6]: df.head()
Out[6]: 
   A          B
0  a   (66, 71]
1  b   (92, 97]
2  c  (98, 103]
3  d   (17, 22]
4  e   (83, 88]

In [7]: df[df['B'].array.contains(70)]
Out[7]: 
     A         B
0    a  (66, 71]
20   a  (68, 73]
23   d  (67, 72]
27   c  (66, 71]
45   a  (69, 74]
87   c  (67, 72]
111  b  (65, 70]
128  d  (68, 73]
133  d  (65, 70]
135  a  (67, 72]
155  a  (65, 70]
177  c  (69, 74]
193  d  (67, 72]
217  c  (69, 74]
221  b  (66, 71]
223  d  (69, 74]
227  c  (66, 71]
243  d  (66, 71]
250  a  (67, 72]
251  b  (65, 70]
263  d  (68, 73]
407  c  (65, 70]
419  e  (69, 74]
425  a  (65, 70]
446  b  (69, 74]
449  e  (69, 74]
451  b  (66, 71]
523  d  (66, 71]
552  c  (68, 73]
589  e  (66, 71]
609  e  (69, 74]
613  d  (68, 73]
627  c  (69, 74]
637  c  (68, 73]
650  a  (67, 72]
674  e  (69, 74]
711  b  (69, 74]
769  e  (67, 72]
777  c  (69, 74]
800  a  (66, 71]
803  d  (68, 73]
818  d  (69, 74]
822  c  (67, 72]
883  d  (66, 71]
889  e  (68, 73]
944  e  (67, 72]
953  d  (69, 74]
966  b  (65, 70]

混合的closed间隔会产生一个object数组,因此您需要使用效率较低的实现,如@ALollz建议的实现。