如何为 "interval" 匹配 pandas DataFrame 中的多个列?
How to match multiple columns in pandas DataFrame for an "interval"?
我有以下 pandas DataFrame:
import pandas as pd
df = pd.DataFrame('filename.csv')
print(df)
order start end value
1 1342 1357 category1
1 1459 1489 category7
1 1572 1601 category23
1 1587 1599 category2
1 1591 1639 category1
....
15 792 813 category13
15 892 913 category5
....
因此,有一个 order
列,每列包含许多行,然后是 range/interval 从 start
到 end
的每一行。然后每一行都由某个 value
标记(例如类别 1、类别 2 等)
现在我有了另一个名为 key_df
的数据框。它基本上是完全相同的格式:
import pandas as pd
key_df = pd.DataFrame(...)
print(key_df)
order start end value
1 1284 1299 category4
1 1297 1309 category9
1 1312 1369 category3
1 1345 1392 category29
1 1371 1383 category31
....
1 1471 1501 category31
...
我的目标是获取 key_df
数据帧并检查间隔 start:end
是否与原始数据帧 df
中的任何行匹配。如果是这样,df
中的这一行应该用 key_df
数据帧的 value
值标记。
在我们上面的示例中,数据帧 df
将像这样结束:
order start end value key_value
1 1342 1357 category1 category29
1 1459 1489 category7 category31
....
这是因为如果您查看 key_df
,行
1 1345 1392 category29
with区间1::1345-1392
落在原来df
中的区间1::1342-1357
。同样,key_df
行:
1 1471 1501 category31
对应于df
中的第二行:
1 1459 1489 category7 category31
我不太确定
(1)如何在pandas中完成这个任务
(2) 如何在 pandas
中有效地扩展它
可以从 if 语句开始,例如
if df.order == key_df.order:
# now check intervals...somehow
但这并没有利用数据帧结构。然后必须按时间间隔检查,即 (df.start =< key_df.start) && (df.end => key_df.end)
我卡住了。在 pandas 中匹配 "interval" 中的多个列的最有效方法是什么? (如果满足此条件,则创建一个新列很简单)
你可以使用merge
with boolean indexing
,但是如果DataFrames
很大,缩放就会有问题:
df1 = pd.merge(df, key_df, on='order', how='outer', suffixes=('','_key'))
df1 = df1[(df1.start <= df1.start_key) & (df1.end <= df1.end_key)]
print (df1)
order start end value start_key end_key value_key
3 1 1342 1357 category1 1345.0 1392.0 category29
4 1 1342 1357 category1 1371.0 1383.0 category31
5 1 1342 1357 category1 1471.0 1501.0 category31
11 1 1459 1489 category7 1471.0 1501.0 category31
通过评论编辑:
df1 = pd.merge(df, key_df, on='order', how='outer', suffixes=('','_key'))
df1 = df1[(df1.start <= df1.start_key) & (df1.end <= df1.end_key)]
df1 = pd.merge(df, df1, on=['order','start','end', 'value'], how='left')
print (df1)
order start end value start_key end_key value_key
0 1 1342 1357 category1 1345.0 1392.0 category29
1 1 1342 1357 category1 1371.0 1383.0 category31
2 1 1342 1357 category1 1471.0 1501.0 category31
3 1 1459 1489 category7 1471.0 1501.0 category31
4 1 1572 1601 category23 NaN NaN NaN
5 1 1587 1599 category2 NaN NaN NaN
6 1 1591 1639 category1 NaN NaN NaN
7 15 792 813 category13 NaN NaN NaN
8 15 892 913 category5 NaN NaN NaN
我有以下 pandas DataFrame:
import pandas as pd
df = pd.DataFrame('filename.csv')
print(df)
order start end value
1 1342 1357 category1
1 1459 1489 category7
1 1572 1601 category23
1 1587 1599 category2
1 1591 1639 category1
....
15 792 813 category13
15 892 913 category5
....
因此,有一个 order
列,每列包含许多行,然后是 range/interval 从 start
到 end
的每一行。然后每一行都由某个 value
标记(例如类别 1、类别 2 等)
现在我有了另一个名为 key_df
的数据框。它基本上是完全相同的格式:
import pandas as pd
key_df = pd.DataFrame(...)
print(key_df)
order start end value
1 1284 1299 category4
1 1297 1309 category9
1 1312 1369 category3
1 1345 1392 category29
1 1371 1383 category31
....
1 1471 1501 category31
...
我的目标是获取 key_df
数据帧并检查间隔 start:end
是否与原始数据帧 df
中的任何行匹配。如果是这样,df
中的这一行应该用 key_df
数据帧的 value
值标记。
在我们上面的示例中,数据帧 df
将像这样结束:
order start end value key_value
1 1342 1357 category1 category29
1 1459 1489 category7 category31
....
这是因为如果您查看 key_df
,行
1 1345 1392 category29
with区间1::1345-1392
落在原来df
中的区间1::1342-1357
。同样,key_df
行:
1 1471 1501 category31
对应于df
中的第二行:
1 1459 1489 category7 category31
我不太确定
(1)如何在pandas中完成这个任务
(2) 如何在 pandas
中有效地扩展它可以从 if 语句开始,例如
if df.order == key_df.order:
# now check intervals...somehow
但这并没有利用数据帧结构。然后必须按时间间隔检查,即 (df.start =< key_df.start) && (df.end => key_df.end)
我卡住了。在 pandas 中匹配 "interval" 中的多个列的最有效方法是什么? (如果满足此条件,则创建一个新列很简单)
你可以使用merge
with boolean indexing
,但是如果DataFrames
很大,缩放就会有问题:
df1 = pd.merge(df, key_df, on='order', how='outer', suffixes=('','_key'))
df1 = df1[(df1.start <= df1.start_key) & (df1.end <= df1.end_key)]
print (df1)
order start end value start_key end_key value_key
3 1 1342 1357 category1 1345.0 1392.0 category29
4 1 1342 1357 category1 1371.0 1383.0 category31
5 1 1342 1357 category1 1471.0 1501.0 category31
11 1 1459 1489 category7 1471.0 1501.0 category31
通过评论编辑:
df1 = pd.merge(df, key_df, on='order', how='outer', suffixes=('','_key'))
df1 = df1[(df1.start <= df1.start_key) & (df1.end <= df1.end_key)]
df1 = pd.merge(df, df1, on=['order','start','end', 'value'], how='left')
print (df1)
order start end value start_key end_key value_key
0 1 1342 1357 category1 1345.0 1392.0 category29
1 1 1342 1357 category1 1371.0 1383.0 category31
2 1 1342 1357 category1 1471.0 1501.0 category31
3 1 1459 1489 category7 1471.0 1501.0 category31
4 1 1572 1601 category23 NaN NaN NaN
5 1 1587 1599 category2 NaN NaN NaN
6 1 1591 1639 category1 NaN NaN NaN
7 15 792 813 category13 NaN NaN NaN
8 15 892 913 category5 NaN NaN NaN