标签:记录 time 数据 row 有关 object 多列 str ict
近期并没有什么系统性的学习感悟,反而是在项目过程中练就了一些奇技淫巧。最近做的工作大部分都跟优化执行效率有关,把原来要泡茶等的代码优化到快如闪电,有时候还是非常有意思的,顺便跟大神们聊天也受益良多,记录一下最近用到的一些以后可能还会反复用的技巧吧:
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)
快如闪电!现已加入特征工程套餐。
标签:记录 time 数据 row 有关 object 多列 str ict
原文地址:https://www.cnblogs.com/silence-gtx/p/11858869.html