nik*_*osd 6 python performance pandas
我试图在数据框上创建一个列,其中包含列A(值列)的最小值,列B(id列)具有特定值.我的代码很慢.我正在寻找一种更快的方法来做到这一点.这是我的小功能:
def apply_by_id_value(df, id_col="id_col", val_col="val_col", offset_col="offset", f=min):
for rid in set(df[id_col].values):
df.loc[df[id_col] == rid, offset_col] = f(df[df[id_col] == rid][val_col])
return df
Run Code Online (Sandbox Code Playgroud)
示例用法:
import pandas as pd
import numpy as np
# create data frame
df = pd.DataFrame({"id_col":[0, 0, 0, 1, 1, 1, 2, 2, 2],
"val_col":[0.1, 0.2, 0.3, 0.6, 0.4, 0.5, 0.2, 0.1, 0.0]})
print df.head(10)
# output
id_col val_col
0 0 0.1
1 0 0.2
2 0 0.3
3 1 0.6
4 1 0.4
5 1 0.5
6 2 0.2
7 2 0.1
8 2 0.0
df = apply_by_id_value(df)
print df.head(10)
# output
id_col val_col offset
0 0 0.1 0.1
1 0 0.2 0.1
2 0 0.3 0.1
3 1 0.6 0.4
4 1 0.4 0.4
5 1 0.5 0.4
6 2 0.2 0.0
7 2 0.1 0.0
8 2 0.0 0.0
Run Code Online (Sandbox Code Playgroud)
更多上下文:在我的实际数据中,"id_col"列有大约30000个或更多的唯一值.这意味着数据帧必须切片30000次.我想这是瓶颈.
执行groupby
'id_col',然后执行transform
传递函数'min',这将返回与原始df对齐的Series,以便您可以添加为新列:
In [13]:
df = pd.DataFrame({"id_col":[0, 0, 0, 1, 1, 1, 2, 2, 2],
"val_col":[0.1, 0.2, 0.3, 0.6, 0.4, 0.5, 0.2, 0.1, 0.0]})
df['offset'] = df.groupby('id_col').transform('min')
df
Out[13]:
id_col val_col offset
0 0 0.1 0.1
1 0 0.2 0.1
2 0 0.3 0.1
3 1 0.6 0.4
4 1 0.4 0.4
5 1 0.5 0.4
6 2 0.2 0.0
7 2 0.1 0.0
8 2 0.0 0.0
Run Code Online (Sandbox Code Playgroud)
计时
In [15]:
def apply_by_id_value(df, id_col="id_col", val_col="val_col", offset_col="offset", f=min):
for rid in set(df[id_col].values):
df.loc[df[id_col] == rid, offset_col] = f(df[df[id_col] == rid][val_col])
return df
%timeit apply_by_id_value(df)
%timeit df.groupby('id_col').transform('min')
100 loops, best of 3: 8.12 ms per loop
100 loops, best of 3: 5.99 ms per loop
Run Code Online (Sandbox Code Playgroud)
因此,在这个数据集中,groupby
并且transform
速度更快,我希望它在真实数据集上的速度要快得多,因为它会更好地扩展.
对于800,000行df,我得到以下时间:
1 loops, best of 3: 611 ms per loop
1 loops, best of 3: 438 ms per loop
Run Code Online (Sandbox Code Playgroud)