zoukankan      html  css  js  c++  java
  • 野路子码农系列(7)近期花里胡哨技巧汇总

    近期并没有什么系统性的学习感悟,反而是在项目过程中练就了一些奇技淫巧。最近做的工作大部分都跟优化执行效率有关,把原来要泡茶等的代码优化到快如闪电,有时候还是非常有意思的,顺便跟大神们聊天也受益良多,记录一下最近用到的一些以后可能还会反复用的技巧吧:

    1、在array中储存tuple

    你试过在array中储存tuple吗?这个问题有些蛋疼,但特殊需求没办法。我一开始以为这个问题很简单,但没想到tuple进去全变list了……导致我后来找某个特定的tuple时提示找不到。有人可能会说list和tuple差不多啊,但tuple是hashable的,这也是我们坚持要tuple的原因。

    idx = [("a", 1), ("a", 2), ("b", 5)]
    np.array(idx)

    你得到的结果会是:

    array([['a', '1'],
           ['a', '2'],
           ['b', '5']], dtype='<U1')

    惊不惊喜?意不意外?后来总算找到了一种方法,必须先新建一个空的array,并制定dtype,之后再赋值:

    arr = np.empty((len(idx)), dtype="object")
    arr[:] = idx
    arr

    现在你得到的结果是:

    array([('a', 1), ('a', 2), ('b', 5)], dtype=object)

    2、数值最大(或最小)的前n项所对应的对象

    有点绕口,举个例子说,我有学生ABCDE,我还有一次考试的成绩,我想知道班级前三是谁。我原来想的是用OrderedDict,后来大神教了我正宗numpy方法,速度当然没的说:

    # 最小前3项(带排序)
    student = np.array(["A", "B", "C", "D", "E", "F", "G"])
    score = np.array([92, 84, 93, 85, 83, 88, 91])
    nth = 3
    
    student[np.argpartition(score, nth-1)[:nth]]

    结果:

    array(['E', 'B', 'D'], dtype='<U1')

    如果要最大,加个负号就行了:

    # 最大前4项(带排序)
    student = np.array(["A", "B", "C", "D", "E", "F", "G"])
    score = np.array([92, 84, 93, 85, 83, 88, 91])
    nth = 4
    
    student[np.argpartition(-score, nth-1)[:nth]]

    结果:

    array(['C', 'A', 'G', 'F'], dtype='<U1')

    3、函数矢量化(向量化)

    你有没有过apply的痛苦经验?当数据量不断增大之后,你会发现稍微复杂的一个apply会变得非常慢,尤其是涉及多列的apply。这时候要如何才能摆脱龟速呢?我当时第一想法是numba?然而numba不用@njit相当于白用,但@njit不支持很多python原生的类型(比如dict),更别谈支持DataFrame了。这时候你需要的是np.vectorize:

    首先我们随便弄一些数据,先来个5W行吧

    df = pd.DataFrame({"a":np.random.random(50000), "b":np.random.random(50000)})

    然后我们的函数是个基于a、b两列的条件判断:

    def func(a, b):
        if (a < 0.5) & (b < 0.5):
            return 1
        elif (a >=0.5) & (b < 0.5):
            return 2
        else:
            return 3

    按照传统的apply方法我们运行一下:

    %%timeit
    df["c"] = df.apply(lambda row: func(row["a"], row["b"]), axis=1)

    结果:

    1.11 s ± 32.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

    好了,现在上魔法,只需短短一行:

    v_func = np.vectorize(func)

    再来计时一下看看:

    %%timeit
    df["c"] = v_func(df["a"], df["b"])

    结果:

    13.4 ms ± 294 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

    快如闪电!现已加入特征工程套餐。

  • 相关阅读:
    数据结构中的知识
    Java中的小知识
    安装Linux虚拟机
    2.Two Sum
    1005. Maximize Sum Of Array After K Negations
    Leetcode刷题记录
    Markdown的使用笔记
    CCF历年试题总结
    在Linux上搭建Hadoop
    配置和使用连接池
  • 原文地址:https://www.cnblogs.com/silence-gtx/p/11858869.html
Copyright © 2011-2022 走看看