微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

python – 应用/ vectorize /加速列式清理功能到pandas dataframe

我有一些数据管道代码,它根据名称将转换/清理逻辑应用于Pandas数据帧的列.

现在我正在使用df.iteritems()迭代列,根据this guide优化Pandas应用函数优于粗循环但是“运行大多数标准函数的效率最低的方法”.

我想通过利用Pandas对这些操作进行矢量化的能力或其他一些并行方法来提高此代码性能.

我见过的所有工作示例都说明了如何按行进行此操作(例如,在一个系列上进行计算而不是在一行上进行计算)但我无法找到如何执行此列的良好示例 – 明智的.

这是一个使用来自scikit learn的Boston数据集的可重现/玩具示例.期望的结果是以矢量化/并行方式实现清理逻辑(不使用.iteritems()或循环).谢谢!

from typing import Callable

# sample df from sklearn
from sklearn import datasets
boston = datasets.load_boston()
boston = pd.DataFrame(boston.data, columns=boston.feature_names)
boston.head()

def double_it(col: pd.Series) -> pd.Series:
    return col.multiply(2)

def make_string(col: pd.Series) -> pd.Series:
    return col.astype(str)

def do_nothing(col: pd.Series) -> pd.Series:
    return col

def match_cleaner(col_name: str) -> Callable:
    if col_name in ['ZN', 'NOX', 'INDUS', 'AGE']:
        return double_it
    elif col_name in ['TAX', 'dis', 'CHAS', 'PTRATIO']:
        return make_string
    else:
        print(col_name)
        return do_nothing

for key, value in boston.iteritems():
    cleaning_func = match_cleaner(key)
    boston.loc[:, key] = cleaning_func(value)

# confirm changes
boston.head()
print(boston.dtypes)

解决方法:

您可以使用pandas.DataFrame.apply.认情况下,apply方法将在数据框的所有列中应用提供的函数.但是你需要修改一下match_cleaner函数.

def match_cleaner2(col):
     col_name = col.name
     if col_name in ['ZN', 'NOX', 'INDUS', 'AGE']:
         return double_it(col)
     elif col_name in ['TAX', 'dis', 'CHAS', 'PTRATIO']:
         return make_string(col)
     else:
         return do_nothing(col)

b2 = boston.apply(match_cleaner2)
b2.head()
      CRIM             ZN          INDUS  ...   PTRATIO       B  LSTAT
0  0.00632  3.932955e+246  5.047292e+245  ...      15.3  396.90   4.98
1  0.02731   0.000000e+00  1.544777e+246  ...      17.8  396.90   9.14
2  0.02729   0.000000e+00  1.544777e+246  ...      17.8  392.83   4.03
3  0.03237   0.000000e+00  4.763245e+245  ...      18.7  394.63   2.94
4  0.06905   0.000000e+00  4.763245e+245  ...      18.7  396.90   5.33

%timeit boston.apply(match_cleaner2)
3.68 ms ± 68.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

def original():
     for k, v in boston.iteritems():
         clean_f = match_cleaner(k)
         boston.loc[:, k] = clean_f(v)

original()
boston.head()
      CRIM             ZN          INDUS  ...   PTRATIO       B  LSTAT
0  0.00632  3.932955e+246  5.047292e+245  ...      15.3  396.90   4.98
1  0.02731   0.000000e+00  1.544777e+246  ...      17.8  396.90   9.14
2  0.02729   0.000000e+00  1.544777e+246  ...      17.8  392.83   4.03
3  0.03237   0.000000e+00  4.763245e+245  ...      18.7  394.63   2.94
4  0.06905   0.000000e+00  4.763245e+245  ...      18.7  396.90   5.33


pd.testing.assert_frame_equal(b2, boston) # boston was modified in place

# No AssertionError means frames are equal

%timeit original()
6.14 ms ± 278 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

因此,从一个非常粗略的实验中,应用函数看起来可以加快这个速度达到约40%.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐