我使用pandas IntervalIndex设置了一个问题,类似于here和here提出的问题,但是由于差异导致我无法成功实施他们的解决方案。
我有两个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
中的end
和df2
可用于定义间隔。我的实际数据要大得多,df1
大约100,000行,df2
大约10,000行。
我想要做的是将period
变量分配到df1
,匹配month
,group
,以及df1['time']
是否在区间内在df2
。
上述问题中出现的问题有两个并发症:
IntervalIndex
只需要MultiIndex
的一部分,匹配需要在索引的所有三个级别上进行。
有时,df1
中存在的时间与df2
中的时间间隔不匹配。如果这些行填充了NaN
或其他缺失值,或者它们刚刚被删除,我就不会有强烈的偏好,但我无法拥有的是{{1} }。
我的第一步是:
KeyError
将IntervalIndex应用于df2Index = pd.IntervalIndex.from_arrays(df2['start'], df2['end'], closed='left')
df2.set_index(df2Index, append=True, inplace=True)
,同时将df2
和month
保持为更高级别的索引。
我尝试了一些方法,例如
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
的两行)。
我的备份计划是循环遍历NaN
和month
的相关组合,适当地对两个表进行子集,在这些子表上使用IntervalIndex,然后重新组合它们。但这似乎是错误的解决方案。
答案 0 :(得分:0)
我希望merge
使用左连接将两个帧组合在一起,然后过滤以仅显示time
在所需start
和end
时段内的行:< / 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('-','').