将IntervalIndex作为MultiIndex

时间:2018-03-27 23:40:35

标签: python pandas dataframe

我使用pandas IntervalIndex设置了一个问题,类似于herehere提出的问题,但是由于差异导致我无法成功实施他们的解决方案。

我有两个DataFrame,构造如下:

df1

    month   group   time    distance
0   1       A       10      100
1   1       A       20      120
2   1       A       25      110
3   1       B       5       90
4   1       B       7       99
5   1       B       17      60
6   1       C       30      200
7   1       C       35      170
8   2       A       5       40
9   2       A       10      27
10  2       B       17      33
11  2       B       19      65

df1.set_index(['month', 'group', 'time'], inplace=True)

df2

    month   group   start   end     period
0   1       A       5       15      1
1   1       A       15      21      2
2   1       A       21      30      3
3   1       B       2       10      1
4   1       B       10      20      2
5   2       A       3       8       1
6   2       A       8       15      2
7   2       B       10      20      1

df2.set_index(['month', 'group'], inplace=True)

start中的enddf2可用于定义间隔。我的实际数据要大得多,df1大约100,000行,df2大约10,000行。

我想要做的是将period变量分配到df1,匹配monthgroup,以及df1['time']是否在区间内在df2

上述问题中出现的问题有两个并发症:

  1. IntervalIndex只需要MultiIndex的一部分,匹配需要在索引的所有三个级别上进行。

  2. 有时,df1中存在的时间与df2中的时间间隔不匹配。如果这些行填充了NaN或其他缺失值,或者它们刚刚被删除,我就不会有强烈的偏好,但我无法拥有的是{{1} }。

  3. 我的第一步是:

    KeyError

    将IntervalIndex应用于df2Index = pd.IntervalIndex.from_arrays(df2['start'], df2['end'], closed='left') df2.set_index(df2Index, append=True, inplace=True) ,同时将df2month保持为更高级别的索引。

    我尝试了一些方法,例如

    group

    但我无法获得正确的索引行为。为了完整起见,我希望的结果是:

    period = df2.loc[df2.index.get_indexer(df1.index), 'period']
    period = df2.get_loc(df1.index), 'period']
    

    (或同一个表但没有 month group time distance period 0 1 A 10 100 1 1 1 A 20 120 2 2 1 A 25 110 3 3 1 B 5 90 1 4 1 B 7 99 1 5 1 B 17 60 2 6 1 C 30 200 NaN 7 1 C 35 170 NaN 8 2 A 5 40 1 9 2 A 10 27 2 10 2 B 17 33 1 11 2 B 19 65 1 period的两行)。

    我的备份计划是循环遍历NaNmonth的相关组合,适当地对两个表进行子集,在这些子表上使用IntervalIndex,然后重新组合它们。但这似乎是错误的解决方案。

2 个答案:

答案 0 :(得分:0)

我希望merge使用左连接将两个帧组合在一起,然后过滤以仅显示time在所需startend时段内的行:< / p>

import pandas as pd

# setup the frame
df1 = pd.DataFrame(
    data={
        'month': [1,1,1,1,1,1,1,1,2,2,2,2],
        'group': ['A','A','A','B','B','B','C','C','A','A','B','B'],
        'time': [10,20,25,5,7,17,30,35,5,10,17,19],
        'distance': [100,120,110,90,99,60,200,170,40,27,33,65],
    })

df2 = pd.DataFrame(
    data={
        'month': [1,1,1,1,1,2,2,2],
        'group': ['A','A','A','B','B','A','A','B'],
        'start': [5,15,21,2,10,3,8,10],
        'end': [15,21,30,10,20,8,15,20],
        'period': [1,2,3,1,2,1,2,1],
    })

# merge, and filter
df = df1.merge(df2, how='left', on=['month','group'])
df = df[(df.time >= df.start) & (df.time <= df.end)][['month','group','time','distance','period']].reset_index(drop=True)

print df

    month   group   time    distance    period
0   1       A       10      100         1.0
1   1       A       20      120         2.0
2   1       A       25      110         3.0
3   1       B       5       90          1.0
4   1       B       7       99          1.0
5   1       B       17      60          2.0
6   2       A       5       40          1.0
7   2       A       10      27          2.0
8   2       B       17      33          1.0
9   2       B       19      65          1.0

请注意,上述框架不包含NaN。如果需要,请更新过滤条件:df[((df.time >= df.start) & (df.time <= df.end)) | (df.period.isnull())]

答案 1 :(得分:-1)

我正试图这样做。我的方法是使用

创建连锁索引列
df.ID.str + df.date.astype(str).replace('-','').