在整个数据框列上有效地应用一个函数

Efficiently applying a function on whole dataframe column

我想对这个数据框的列应用一个函数:

df = pd.DataFrame({"a":[0,1,2,3,4,5,6], "b": [10,100,100,100,100,1000,1]})

def scale(values):
    scaled_values = (values - np.min(values)) / (np.max(values) - np.min(values))
    return scaled_values / np.sum(scaled_values)

此函数需要同时考虑列中的所有值。因此,我无法使用 pandas 的“应用”方法应用该功能。因此目前我只是打电话给

df.loc[:,"a"] = scale(df["a"])
df.loc[:,"b"] = scale(df["b"])

但是,如果我有很多列,我不想这样做,而且遍历这些列也很丑陋:

for c in df.columns:
  df.loc[:,c] = scale(df[c])

我想知道是否有一种 pandas 方法可以立即将一种方法“应用”到整个列,这样我就可以摆脱这个丑陋的循环。有什么建议吗?

是的,它调用了DataFrame.apply来处理每一列的函数:

#default axis=0
df = df.apply(scale)
#df = df.apply(scale, axis=0)

print (df)
          a         b
0  0.000000  0.006410
1  0.047619  0.070513
2  0.095238  0.070513
3  0.142857  0.070513
4  0.190476  0.070513
5  0.238095  0.711538
6  0.285714  0.000000

这里可以将所有列一起传递 - 这样性能会更好:

df = scale(df)
#alternative
df = df.pipe(scale)
print (df)
          a         b
0  0.000000  0.006410
1  0.047619  0.070513
2  0.095238  0.070513
3  0.142857  0.070513
4  0.190476  0.070513
5  0.238095  0.711538
6  0.285714  0.000000

性能:

#[70000 rows x 20 columns]
df = pd.concat([df] * 10000, ignore_index=True)
df = pd.concat([df] * 10, axis=1, ignore_index=True)


In [72]: %timeit df.apply(scale)
57.3 ms ± 3.32 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [73]: %timeit df.pipe(scale)
38.5 ms ± 241 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [74]: %timeit scale(df)
38.6 ms ± 780 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)