对照数据帧2中的多个段实例检查数据帧1中的段长度



背景:我有两个Pandas数据帧:

  • DF1表示已知路段,其中>=7%的卡车流量
  • DF2代表研究区域内的所有路段

列:SRI是"标准路线标识符",MP_START是"英里点起点",MP_END是"英里点终点",而TRUCK_PCT是"卡车交通百分比"。

任务:对于DF1中的每一行,任务是检查DF2中的每条记录,以找到两个并发项:

  1. 查找匹配的SRI记录
  2. 在匹配的SRI记录中,查找DF2DF2.MP_STARTDF2.MP_END值中存在DF1.MP_STARTDF1.MP_END值的行
  3. 然后按照上述条件将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.30DF1.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_STARTDF2MP_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_STARTMP_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%

相关内容

最新更新