我有以下数据框,其中包含与列设置相对应的值 -
import pandas as pd
data_0 = {'setting':[0,0,0,0,1,1,1,2,2,2,2,2,2],
'values': [0, 1, 2, 3, 0, 1, 2, 0,1,2,3, 5,6]
}
df_0 = pd.DataFrame(data_0)
我有另一个数据框,其中包含每个设置的相关开始值和结束值 -
data_1 = {'setting':[0,1,2,2],
'start_value': [1,0,1,3],
'end_value':[3,2,3,6]
}
df_1 = pd.DataFrame(data_1)
现在,我想根据 df_1 中的 start_value 和 end_value 从 df_0 中提取值。
最终输出应如下所示 -
data_2 = {'setting':[0,0,1,1,2,2,2,2],
'start_value': [1,1,0,0,1,1,3,3],
'end_value':[3,3,2,2,3,3,6,6],
'values_from_data_0':[1,2,0,1,1,2,3,5]
}
df_2 = pd.DataFrame(data_2)
setting start_value end_value values_from_data_0
0 0 1 3 1
1 0 1 3 2
2 1 0 2 0
3 1 0 2 1
4 2 1 3 1
5 2 1 3 2
6 2 3 6 3
7 2 3 6 5
请注意 setting = 2
列对应的缺失值 4。
这是我天真的(也是错误的)尝试 -
import numpy as np
list_final = []
for index, row in df_1.iterrows():
value_start = row['start_value']
value_end = row['end_value']
assert value_start<value_end
values = np.arange(value_start, value_end)
list_final.append(values)
df_1["values_from_data_0"] = list_final
df_1 = df_1.explode('values_from_data_0')
print(df_1)
这几乎是正确的。但是,由于它没有从 df_0
获取值,而是使用 arange
,因此结果是错误的。
最佳答案
假设设置中的间隔不重叠,您需要使用 merge_asof
:
out = (pd.merge_asof(df_0.reset_index().sort_values(by='values'),
df_1.sort_values(by='start_value'),
by='setting', left_on='values', right_on='start_value')
.query('values < end_value')
.set_index('index').sort_index()
.rename(columns={'values': 'values_from_data_0'})
)
或者,使用 janitor
的conditional_join
:
# pip install pyjanitor
import janitor
out = (df_0.conditional_join(df_1,
('setting', 'setting', '=='),
('values', 'start_value', '>='),
('values', 'end_value', '<'),
df_columns = {'values': 'values_from_data_0'}
)
)
输出:
values_from_data_0 setting start_value end_value
0 1 0 1 3
1 2 0 1 3
2 0 1 0 2
3 1 1 0 2
4 1 2 1 3
5 2 2 1 3
6 3 2 3 6
7 5 2 3 6
关于Pandas:如何使用另一列列出一列中存在的起始值和结束值之间的数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77380147/