近期并无什么系统性的学习感悟,反而是在项目过程当中练就了一些奇技淫巧。最近作的工做大部分都跟优化执行效率有关,把原来要泡茶等的代码优化到快如闪电,有时候仍是很是有意思的,顺便跟大神们聊天也受益良多,记录一下最近用到的一些之后可能还会反复用的技巧吧:python
一、在array中储存tupleapp
你试过在array中储存tuple吗?这个问题有些蛋疼,但特殊需求没办法。我一开始觉得这个问题很简单,但没想到tuple进去全变list了……致使我后来找某个特定的tuple时提示找不到。有人可能会说list和tuple差很少啊,但tuple是hashable的,这也是咱们坚持要tuple的缘由。dom
idx = [("a", 1), ("a", 2), ("b", 5)] np.array(idx)
你获得的结果会是:函数
array([['a', '1'], ['a', '2'], ['b', '5']], dtype='<U1')
惊不惊喜?意不意外?后来总算找到了一种方法,必须先新建一个空的array,并制定dtype,以后再赋值:oop
arr = np.empty((len(idx)), dtype="object") arr[:] = idx arr
如今你获得的结果是:学习
array([('a', 1), ('a', 2), ('b', 5)], dtype=object)
二、数值最大(或最小)的前n项所对应的对象优化
有点绕口,举个例子说,我有学生ABCDE,我还有一次考试的成绩,我想知道班级前三是谁。我原来想的是用OrderedDict,后来大神教了我正宗numpy方法,速度固然没的说:spa
# 最小前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]]
结果:code
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')
三、函数矢量化(向量化)
你有没有过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)
快如闪电!现已加入特征工程套餐。