如何找到重叠的intervalIndex熊猫

时间:2020-08-27 08:24:28

标签: python pandas dataframe

我有一个数据框,其中包含索引的上下限,并带有相应的值,并且我正在尝试匹配te相应索引的值。我的数据框包含400.000行。我的数据框示例:

df1 = pd.DataFrame({'low':[4,7,8],'high':[6,7,21],'value':[10,15,20]})
df2 = pd.DataFrame({'index':[4,5,6,7,8,9]})

输出:

  low   high  value
0  4     6     10
1  7     7     15
2  8     21    20

现在,只要索引在之间,我想将df1的添加到df2,结果如下:< / p>

  index  value
0  4      10 
1  5      10
2  6      10
3  7      15
4  8      20
5  9      20

我尝试使用以下帖子制作intervalIndex:Searching a particular value in a range among two columns python dataframe

v = df1.loc[:, 'low':'high'].apply(tuple, 1).tolist()
idx = pd.IntervalIndex.from_tuples(v, 'both')
df2['value'] = df1.iloc[idx.get_indexer(df2['index'].values), 'value'].values

但是我的间隔保持重叠,我删除了重复的版本,但是我仍然需要删除一些重叠的间隔。找到它的一种方法是使用带有以下内容的for循环:

[idx.overlaps(x) for x in idx]

但是这会花费很多时间,并且每次我的内存出现故障时。有找到重叠间隔的快速方法吗?

3 个答案:

答案 0 :(得分:1)

这是一个解决方案假设索引已排序,创建一个带有限制值的dict,对数据框使用dict,然后使用ffill()来填补地图创建的空白。 / p>

between_ = (
    {**df1.set_index('low')['value'].to_dict(),
     **df1.set_index('high')['value'].to_dict()}
)
# {4: 10, 7: 15, 8: 20, 6: 10, 21: 20}

df2['index'].map(between_).ffill()

0    10.0
1    10.0
2    10.0
3    15.0
4    20.0
5    20.0
Name: index, dtype: float64

答案 1 :(得分:1)

构建一个数据框以使用pd.concat()

加入
df1 = pd.DataFrame({'low':[4,7,8],'high':[6,7,21],'value':[10,15,20]})
df2 = pd.DataFrame({'index':[4,5,6,7,8,9]}).set_index("index")

df2 = df2.join(pd.concat([pd.DataFrame(index=pd.RangeIndex(r[0],r[1]+1)).assign(value=r[2]) 
                    for r in df1.values])
         )

输出

       value
index       
4         10
5         10
6         10
7         15
8         20
9         20

答案 2 :(得分:1)

打开此线程已有一段时间了。但是我最近也遇到了类似的问题。我发现使用Pandas IntervalIndex可以很好地解决该问题。

# Create an open IntervalIndex with both ends closed using setting 'both'
interval_idx = pd.IntervalIndex.from_arrays(df1.low, df1.high, 'both')

# Set the interval
df1 = df1.set_index(interval_idx)

# Define a function for getting all matching intervals from a dataframe
def get_interval_value(x, df=None):
    if df is not None:
        try:
            res = df.loc[x].value
        except:
            res = None
    else:
        res = None
    return res

# Compute interval overlaps
df2['value'] = df2['index'].apply(get_interval_value, df=df1)

返回df2的期望结果:

   index  value
0  4      10   
1  5      10   
2  6      10   
3  7      15   
4  8      20   
5  9      20