numpy 使用np.select(),以单值自定义函数作为输入

i2loujxw  于 2023-03-23  发布在  其他
关注(0)|答案(1)|浏览(93)

我有以下示例代码:

data = ['05/21/2021','05/21/2022','05/21/2023']    
df = pd.DataFrame(data, columns=['register_date'])
df['register_year'] = pd.to_datetime(df['register_date']).dt.year
df['study_year'] = 2022

这里,我有一个 Dataframe ,看起来像这样:
| 登记日期|登记年|学习年|
| - ------|- ------|- ------|
| 2019 - 05 - 21 2019 - 05 - 21|小行星2021|小行星2022|
| 2019 - 05 - 21 10:00:00|小行星2022|小行星2022|
| 2019 - 05 - 21 10:00:00|二○二三|小行星2022|
目标是创建另一个名为“duration_start”的列,其中如果register_year < study_year,则为1;如果register_year > study_year,则为0;如果register_year == study_year,则为register_year的年末与注册日期之间的年份比例。
我创建了以下条件,以便与np.select()一起使用

register_year_lt_study_year = df['register_year'] < df['study_year']
register_year_gt_study_year = df['Register_year'] > df['Study_year']

和一个函数,它计算从年末开始的一年的比例:

def proportion_to_year_end(date):
    start = pd.to_datetime(date)
    year_end = pd.to_datetime('12/31/' + str(start.year))
    return (year_end - start).days/365

然而,我不确定应该如何填写??,因为proportion_to_year_end()是一个接受字符串的单值函数,但np.select()接受相同长度的列。
df['duration_start'] = np.select([register_year_lt_study_year, register_year_gt_study_year], [1, 0], ??)
我考虑过使用apply()函数,也许可以生成另一列,然后删除它,但这需要更多的逻辑来首先处理0和1,然后在此之上,应用proportion_to_year_end,然后删除临时列。
或者,我考虑过将proportion_to_year_end()改为两列,但我不确定如何在没有for循环的情况下编写它,这是我们应该避免的。
我想知道是否有更好的方法来解决这类问题,其中单值函数和 Dataframe 中的列之间存在明显的维度不匹配?

osh3o9ms

osh3o9ms1#

np.select的文档表明默认值必须是一个值,所以我认为你不能在那里应用你的函数。
你可以做的一件事是用1 s和0 s部分填充数组,给予数组的其余部分(其中register_year == study_year)一个特定的值,比如nan或-1,并通过掩码填充该部分。例如:

df['duration_start'] = np.select([register_year_lt_study_year, register_year_gt_study_year],
                                 [1, 0],
                                 np.nan)

mask = df['register_year'] == df['study_year']
df['duration_start'][mask] = np.vectorize(proportion_to_year_end)(df['study_year'][mask])

我不得不在这里使用vectorize,但如果您更改proportion_to_year_end以支持datetime数组,我们可以删除它。

相关问题