我的数据框是:
import padnas as pd
df_1 = pd.DataFrame(
{
'a': [10, 12, 14, 20, 25, 30, 42, 50, 80]
}
)
df_2 = pd.DataFrame(
{
'start': [9, 19],
'end': [26, 50],
'label': ['a', 'b']
}
)
预期输出:将列
label
添加到 df_1
:
a label
10 a
12 a
14 a
20 a
25 a
20 b
25 b
30 b
42 b
50 b
df_2
定义标签的范围。例如,范围的 df_2
的第一行开始是 9,结束是 22。现在我想根据开始和结束对 df_1
进行切片,并将此标签赋予切片。请注意,start
是排他性的,而 end
是包容性的。而且我的标签范围重叠。
这些是我的尝试。第一个有效,但我不确定它是否是最好的。
# attempt_1
dfc = pd.DataFrame([])
for idx, row in df_2.iterrows():
start = row['start']
end = row['end']
label = row['label']
df_slice = df_1.loc[df_1.a.between(start, end, inclusive='right')]
df_slice['label'] = label
dfc = pd.concat([df_slice, dfc], ignore_index=True)
## attempt 2
idx = pd.IntervalIndex.from_arrays(df_2['start'], df_2['end'], closed='both')
label = df_2.iloc[idx.get_indexer(df_1.a), 'label']
df_1['label'] = label.to_numpy()
一个快速选项是来自 pyjanitor 的 conditional_join:
# pip install pyjanitor
import pandas as pd
import janitor
(df_1
.conditional_join(
df_2,
('a','start','>='),
('a','end','<='),
df_columns = 'a',
right_columns='label')
)
a label
0 10 a
1 12 a
2 14 a
3 20 a
4 20 b
5 25 a
6 25 b
7 30 b
8 42 b
9 50 b