Pandas:如何列出一列中的起始值和结束值之间的数字,使用另一列?

nnvyjq4y  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(79)

我有下面的框架,其中包含对应于列设置的值-

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

的字符串
请注意,缺少的值4对应于列setting = 2
这是我的天真(和错误)的尝试-

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,因此结果是错误的。

cu6pst1q

cu6pst1q1#

假设设置中的间隔不重叠,则需要使用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'})
      )

字符串
或者,使用janitorconditional_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

vngu2lb8

vngu2lb82#

验证码

tmp = df_0.merge(df_1, how='left')
cond1 = tmp['values'] >= tmp['start_value']
cond2 = tmp['values'] < tmp['end_value']
out = tmp[cond1 & cond2].reset_index(drop=True).iloc[:, [0, 2, 3, 1]]\
                        .rename({'values':'values_from_data_0'}, axis=1)

字符串
输出:

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

n9vozmp4

n9vozmp43#

按照您的explode方法,您可以使用以下方法:

aggvals = df_0.groupby("setting")["values"].agg(list)

out = (df_1.assign(values_from_data_0=[
        [i for i in lst if s<=i<e] for s,e,lst in zip(
         df_1["start_value"], df_1["end_value"], df_1["setting"].map(aggvals))])
     .explode("values_from_data_0", ignore_index=True))

# 1.1 ms ± 14.2 µs per loop (mean ± std. dev. of 7 runs, 1,000 loopseach)

字符串
输出量:

print(out)

   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

相关问题