猿问

Python 多类别比率

我有这个项目需要每年每周的每日比率,如下所示


Week |      Year     | Weekday | Volume

    1         2000         1         0

    1         2000         2        10

    1         2000         3        10

    2         2000         1        10

    2         2000         2         0

    1         2001         1         0

    1         2001         2        10

    1         2001         3        10

    2         2001         1        10

    2         2001         2         0


我希望输出是这样的


Week |      Year     | Weekday | Volume   | Ratio

    1         2000         1         0          0

    1         2000         2        10         .5

    1         2000         3        10         .5

    2         2000         1        10          1

    2         2000         2         0          0

    1         2001         1         0          0

    1         2001         2        10         .5

    1         2001         3        10         .5

    2         2001         1        10          1

    2         2001         2         0          0


我有一个与此类似的当前解决方案


for year in years

    for week in weeks 

        ratio = week/weeklytotal

        weeklyratios = pd.concat([weeklyratios,ratio], blablabla)

这样做的问题是它的效率非常低,尤其是因为我必须执行此过程超过 30k 次。它最终导致 2.3 秒的运行时间相当于长达 24 小时的代码运行时间。


有没有更好的方法可以让它运行得更快?


catspeake
浏览 183回答 2
2回答

暮色呼如

您可以使用 groupby 来计算每周的总数量。然后,您可以将该总体积加入原始数据帧并以矢量化方式计算比率。假设原始数据帧是df(dtype 是int):   Week  Year  Weekday  Volume0     1  2000        1       01     1  2000        2      102     1  2000        3      103     2  2000        1      104     2  2000        2       05     1  2001        1       06     1  2001        2      107     1  2001        3      108     2  2001        1      109     2  2001        2       0您可以使用:s = df.groupby(['Week', 'Year']).sum().drop('Weekday', axis=1)df2 = df.set_index(['Week', 'Year']).join(s,rsuffix='_tot').sort_index(level=1)df2['ratio'] = df2.Volume / df2.Volume_totprint(df2)给出:           Weekday  Volume  Volume_tot  ratioWeek Year                                    1    2000        1       0          20    0.0     2000        2      10          20    0.5     2000        3      10          20    0.52    2000        1      10          10    1.0     2000        2       0          10    0.01    2001        1       0          20    0.0     2001        2      10          20    0.5     2001        3      10          20    0.52    2001        1      10          10    1.0     2001        2       0          10    0.0您可以通过以下方式获得预期输出:print(df2.drop('Volume_tot', axis=1).reset_index())这使:   Week  Year  Weekday  Volume  ratio0     1  2000        1       0    0.01     1  2000        2      10    0.52     1  2000        3      10    0.53     2  2000        1      10    1.04     2  2000        2       0    0.05     1  2001        1       0    0.06     1  2001        2      10    0.57     1  2001        3      10    0.58     2  2001        1      10    1.09     2  2001        2       0    0.0

森栏

您可以使用 Pandas 中的索引和groupby功能来执行分组操作。假设您有一个df包含 ['week','year','weekday','volume'] 列的数据框,您的解决方案将如下所示:import numpy as npimport pandas as pdimport timeit as t# make up some data, only 1000 groups not your 30000, but it gets the point acrossdates = pd.date_range(start = '2000-01-01', end = '2019-02-28', freq = 'D')volume = np.random.randint(0,100,len(dates))df = pd.DataFrame(list(zip(dates.week,dates.year,dates.dayofweek,volume)),                  columns = ['week','year','weekday','volume'])# groupgrp = df.groupby(['year','week'])grp_vol = grp['volume'].sum()# rename to avoid overlap in namesgrp_vol.name  = 'weekly_volume'# rejoin to calculate your ratiodf = df.join(grp_vol, on = ['year','week'])df['ratio'] = df['volume']/df['weekly_volume']然后计时%timeit df['ratio'] = df['volume']/df['weekly_volume']196 µs ± 4.32 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
随时随地看视频慕课网APP

相关分类

Python
我要回答