背景:我有两个Pandas数据帧:
- DF1表示已知路段,其中>=7%的卡车流量
- DF2代表研究区域内的所有路段
列:SRI
是"标准路线标识符",MP_START
是"英里点起点",MP_END
是"英里点终点",而TRUCK_PCT
是"卡车交通百分比"。
任务:对于DF1
中的每一行,任务是检查DF2
中的每条记录,以找到两个并发项:
- 查找匹配的
SRI
记录 - 在匹配的
SRI
记录中,查找DF2
中DF2.MP_START
和DF2.MP_END
值中存在DF1.MP_START
和DF1.MP_END
值的行 - 然后按照上述条件将
DF1.TRUCK_PCT
值分配给DF2
中的正确行。下面是一个例子
样品DF1:
DF1 = pd.DataFrame([['00000009__', 51.30, 52.26, '7%'],
['00000015__', 14.41, 14.71,'12%'],
['00000015__', 14.71, 15.45,'8%'],
['00000015__', 15.45, 15.724,'7%'],
['00000015__', 15.72, 16.25,'8%'],
['00000015__', 16.25, 16.31,'10%'],
['00000015__', 16.31, 16.70, '10%'],
['00000015__', 16.70, 16.89,'11%']], columns=['SRI', 'MP_START', 'MP_END', 'TRUCK_PCT'])
SRI MP_START MP_END TRUCK_PCT
0 00000009__ 51.30 52.260 7%
1 00000015__ 14.41 14.710 12%
2 00000015__ 14.71 15.450 8%
3 00000015__ 15.45 15.724 7%
4 00000015__ 15.72 16.250 8%
5 00000015__ 16.25 16.310 10%
6 00000015__ 16.31 16.700 10%
7 00000015__ 16.70 16.890 11%
样本DF2:
DF2 = pd.DataFrame([['17031021__', 0.0, 0.10],
['03291236__', 0.0, 0.05],
['200006165__', 0.0, 0.12],
['00000009__', 52.36, 52.394],
['00000009__', 51.78, 52.36],
['00000009__', 49.09, 51.78],
['00000009__', 48.76, 48.76],
['00000015__', 15.45, 15.48]], columns=['SRI', 'MP_START', 'MP_END'])
SRI MP_START MP_END
0 17031021__ 0.00 0.100
1 03291236__ 0.00 0.050
2 200006165__ 0.00 0.120
3 00000009__ 52.36 52.394
4 00000009__ 51.78 52.360
5 00000009__ 49.09 51.780
6 00000009__ 48.76 48.760
7 00000015__ 15.45 15.480
预期结果:
对于
DF1.SRI == 00000009__
、DF1.MP_START == 51.30
和DF1.MP_END == 52.260
所在的行:第0行上的
DF1.MP_START
(51.30
(落在DF2
的第5行内,而第0行的DF1.MP_END
(52.26
(落在第4行内。因此,DF2
第4行和第5行都被分配了7%的TRUCK_PCT
值。类似地,在
DF2.SRI == 00000015__
(行7(的情况下,该行将被分配7%的TRUCK_PCT
,因为DF1
的行3包含MP_START
和DF2
的MP_END
值,其中DF1.SRI == DF2.SRI (00000015__)
。
样本DF3输出:
SRI MP_START MP_END TRUCK_PCT
0 17031021__ 0.00 0.100
1 03291236__ 0.00 0.050
2 200006165__ 0.00 0.120
3 00000009__ 52.36 52.394
4 00000009__ 51.78 52.360 7%
5 00000009__ 49.09 51.780 7%
6 00000009__ 48.76 48.760
7 00000015__ 15.45 15.480 7%
免责声明:这是一个令人困惑的问题-请在需要的地方询问更多信息,我会尽力澄清。
一个可能的解决方案是首先合并SRI列上的两个数据帧(将所有行保留在DF2
中(,然后找出哪些行满足重叠范围的次要条件。
首先,合并数据帧,同时保留DF2
的索引供以后使用:
DF2 = DF2.reset_index()
df = pd.merge(DF2, DF1, on='SRI', how='left', suffixes=('', '_range'))
这导致以下数据帧:
index SRI MP_START MP_END MP_START_range MP_END_range TRUCK_PCT
0 0 17031021__ 0.00 0.100 NaN NaN NaN
1 1 03291236__ 0.00 0.050 NaN NaN NaN
2 2 200006165__ 0.00 0.120 NaN NaN NaN
3 3 00000009__ 52.36 52.394 51.30 52.260 7%
4 4 00000009__ 51.78 52.360 51.30 52.260 7%
5 5 00000009__ 49.09 51.780 51.30 52.260 7%
6 6 00000009__ 48.76 48.760 51.30 52.260 7%
7 7 00000015__ 15.45 15.480 14.41 14.710 12%
8 7 00000015__ 15.45 15.480 14.71 15.450 8%
9 7 00000015__ 15.45 15.480 15.45 15.724 7%
10 7 00000015__ 15.45 15.480 15.72 16.250 8%
11 7 00000015__ 15.45 15.480 16.25 16.310 10%
12 7 00000015__ 15.45 15.480 16.31 16.700 10%
13 7 00000015__ 15.45 15.480 16.70 16.890 11%
现在,我们为两个范围列中具有MP_START
或MP_END
的行创建一个布尔索引。任何不满足这些条件之一的行的TRUCK_PCT
值都设置为nan:
cond_start = (df['MP_START'] >= df['MP_START_range']) & (df['MP_START'] < df['MP_END_range'])
cond_end = (df['MP_END'] >= df['MP_START_range']) & (df['MP_END'] < df['MP_END_range'])
df.loc[~(cond_start | cond_end), 'TRUCK_PCT'] = np.nan
最后,我们可以删除两个范围列,并按照之前创建的索引进行分组,以获得最终结果。这将保留DF2
中与DF1
:不匹配的任何行
df = df.drop(columns=['MP_START_range', 'MP_END_range']).groupby('index').first().fillna('')
结果:
SRI MP_START MP_END TRUCK_PCT
index
0 17031021__ 0.00 0.100
1 03291236__ 0.00 0.050
2 200006165__ 0.00 0.120
3 00000009__ 52.36 52.394
4 00000009__ 51.78 52.360 7%
5 00000009__ 49.09 51.780 7%
6 00000009__ 48.76 48.760
7 00000015__ 15.45 15.480 7%