本篇内容主要讲解“怎么避免编写pandas代码”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么避免编写pandas代码”吧!
设置
from platform importpython_versionimport numpy as np import pandas as pdnp.random.seed(42) # set the seed tomake examples repeatable
样本数据集
样本数据集包含各个城市的预订信息,是随机的,唯一目的是展示样本。
数据集有三列:
id表示唯一的标识
city表示预定的城市信息
booked perc表示特定时间预定的百分比
数据集有一万条,这使速度改进更加明显。注意,如果代码以正确的pandas方式编写,pandas可以利用DataFrames计算数百万(甚至数十亿)行的统计数据。
size = 10000cities =["paris", "barcelona", "berlin", "newyork"]df = pd.DataFrame( {"city": np.random.choice(cities,sizesize=size), "booked_perc": np.random.rand(size)} ) df["id"] = df.index.map(str) +"-" + df.city dfdf = df[["id", "city", "booked_perc"]] df.head()
1. 如何避免对数据求和
来自Java世界的灵感,把“多行for循环”应用到了Python。
计算booked perc列的总和,把百分比加起来毫无意义,但无论如何,一起来试试吧,实践出真知。
%%timeitsuma = 0 for _, row in df.iterrows(): suma += row.booked_perc766ms ± 20.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
更符合Python风格的方式来对列求和如下:
%%timeitsum(booked_perc forbooked_perc in df.booked_perc)989 µs ± 18.5 µs per loop (mean ±std. dev. of 7 runs, 1000 loops each)%%timeitdf.booked_perc.sum()92µs ± 2.21 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
正如预期的那样,第一个示例是最慢的——对一万项求和几乎需要1秒。第二个例子的速度之快令人惊讶。
正确的方法是使用pandas对数据进行求和(或对列使用任何其他操作),这是第三个示例——也是最快的!
2. 如何避免过滤数据
尽管在使用pandas之前,笔者已经很熟悉numpy,并使用for循环来过滤数据。求和时,还是可以观察到性能上的差异。
%%timeitsuma = 0 for _, row in df.iterrows(): if row.booked_perc <=0.5: suma += row.booked_perc831ms ± 25.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)%%timeitdf[df.booked_perc<= 0.5].booked_perc.sum()724 µs ± 18.8 µs per loop(mean ± std. dev. of 7 runs, 1000 loops each)
正如预期的一样,第二个例子比第一个例子快很多
如果加入更多的过滤器呢?只需把它们添加到括号里:
%%timeitdf[(df.booked_perc <=0.5) & (df.city == 'new york')].booked_perc.sum()1.55ms ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3. 如何避免访问以前的值
你可能会说:好吧,但是如果需要访问先前某一列的值呢,还是需要一个for循环。你错了!
分别使用和不使用for循环来计算一行到另一行百分数的改变
%%timeitfor i inrange(1, len(df)): df.loc[i,"perc_change"] = (df.loc[i].booked_perc- df.loc[i - 1].booked_perc) / df.loc[i- 1].booked_perc7.02 s ± 24.4 ms per loop (mean ± std. dev. of 7runs, 1 loop each)%%timeitdf["perc_change"] = df.booked_perc.pct_change()586µs ± 17.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
同样,第二个例子比第一个使用for循环的例子快得多。
pandas有许多函数可以根据以前的值计算统计数据(例如shift函数对值进行移位)。这些函数接受periods参数,可以在计算中包含以前值的数量。
4. 如何避免使用复杂的函数
有时需要在DataFrame中使用复杂函数(有多个变量的函数)。让我们将从纽约的booking_perc两两相乘,其他设置为0并且把这列命名为sales_factor。
笔者首先想到的是使用iterrows的for循环。
%%timeitfor i, row in df.iterrows(): if row.city =='new york': df.loc[i, 'sales_factor'] =row.booked_perc * 2 else: df.loc[i, 'sales_factor'] =03.58 s ± 48.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
一个更好的办法是直接在DataFrame上使用函数。
%%timeitdef calculate_sales_factor(row): if row.city =='new york': return row.booked_perc* 2 return 0df['sales_factor'] =df.apply(calculate_sales_factor, axis=1)165 ms ± 2.48 ms per loop(mean ± std. dev. of 7 runs, 10 loops each)
最快的方法是使用pandas过滤器直接计算函数值。
%%timeit df.loc[df.city== 'new york', 'sales_factor'] = df[df.city == 'newyork'].booked_perc * 2 df.sales_factor.fillna(0, inplace=True)3.03 ms ± 85.5 µsper loop (mean ± std. dev. of 7 runs, 100 loops each)
可以看到从第一个例子到最后一个的加速过程。
当解决有3个及3个以上变量的函数时,可以把它分解为多个pandas表达式。这比运用函数更快。
Eg: f(x, a, b) = (a + b) * x df['a_plus_b'] = df['a'] +df['b'] df['f'] = df['a_plus_b'] * df['x']
5. 如何避免对数据进行分组
现在可以看到,在开始使用pandas之前,笔者更多依赖于for循环。至于对数据进行分组,如果充分发挥pandas的优势,可以减少代码行数。
要计算如下数据:
一个城市的平均sales factor
一个城市的首次预定id
%%timeit avg_by_city = {} count_by_city = {} first_booking_by_city = {}for i, row in df.iterrows(): city = row.city if city in avg_by_city: avg_by_city[city] += row.sales_factor count_by_city[city] += 1 else: avg_by_city[city] = row.sales_factor count_by_city[city] = 1 first_booking_by_city[city] =row['id']for city, _ in avg_by_city.items(): avg_by_city[city] /=count_by_city[city]878 ms ± 21.4 ms per loop (mean ± std. dev. of 7 runs, 1 loopeach)
Pandas有分组操作所以不必在DataFrame上进行迭代,pandas的分组操作和SQL的GROUP BY语句一样的。
%%timeitdf.groupby('city').sales_factor.mean() df.groupby('city').sales_factor.count() df.groupby('city').id.first()3.05 ms ± 65.3 µs per loop(mean ± std. dev. of 7 runs, 100 loops each)%%timeitdf.groupby("city").agg({"sales_factor":["mean", "count"], "id": "first"})4.5ms ± 131 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
到此,相信大家对“怎么避免编写pandas代码”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!