在Pandas中创建新列的方法很多(我可能在我的示例中漏掉了一些,所以请告诉我是否有其他列,我将在这里介绍),我想找出使用每种方法的最佳时机。显然,某些方法在某些情况下比其他方法更好,但我想从整体的角度来评估它:效率、可读性和有用性。
我主要关注的是第一个三种,但是包含了其他方法,仅仅是为了说明使用不同的方法是可能的。这是你的样本dataframe
df = pd.DataFrame({'a':[1,2,3],'b':[4,5,6]})最常见的方法是命名一个新列,如df['c'],并使用apply
df['c'] = df['a'].apply(lambda x: x * 2)
df
a b c
0 1 4 2
1 2 5 4
2 3 6 6使用assign可以完成相同的任务:
df = df.assign(c = lambda x: x['a'] * 2)
df
a b c
0 1 4 2
1 2 5 4
2 3 6 6通过@roganjosh更新:
df['c'] = df['a'] * 2
df
a b c
0 1 4 2
1 2 5 4
2 3 6 6使用map (肯定不如apply那么高效):
df['c'] = df['a'].map(lambda x: x * 2)
df
a b c
0 1 4 2
1 2 5 4
2 3 6 6创建一个新的pd.series,然后concat将其带入dataframe
c = pd.Series(df['a'] * 2).rename("c")
df = pd.concat([df,c], axis = 1)
df
a b c
0 1 4 2
1 2 5 4
2 3 6 6使用join
df.join(c)
a b c
0 1 4 2
1 2 5 4
2 3 6 6发布于 2018-07-26 16:22:25
简短的回答:矢量化调用(df['c'] = 2 * df['a'])几乎总是在速度和可读性两方面都获胜。关于在性能方面可以使用什么作为选项的“层次结构”,请参见this答案。
在一般情况下,如果在Pandas操作中有一个for i in ...或lambda,这(有时)意味着生成的计算调用Python代码,而不是Pandas的Cython库所依赖的优化C代码来进行矢量化操作。(对于依赖于底层NumPy的.values的操作也是如此。)
对于.assign(),注释中正确地指出,这会创建一个副本,而您可以将df['c'] = 2 * df['a']看作相当于设置字典键/值。前者所需的时间也是前者的两倍,虽然这可能有点过时,因为一个操作正在返回一个DataFrame,而另一个操作只是分配一个列。
>>> %timeit df.assign(c=df['a'] * 2)
498 µs ± 15.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit -r 7 -n 1000 df['c'] = df['a'] * 2
239 µs ± 22.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)对于.map():通常,正如名称所暗示的那样,当您希望为一个系列提供一个映射时(尽管它可以被传递给一个函数,就像在您的问题中一样),您就会看到这一点。这并不意味着它不具有表现力,它只是在我见过的情况下被用作一种专门的方法:
>>> df['a'].map(dict(enumerate('xyz', 1)))
0 x
1 y
2 z
Name: a, dtype: object至于.apply():为了给答案注入一点意见,我认为在可能的情况下使用矢量化更为惯用。您可以在 is defined的代码中看到:因为您传递的是一个lambda,而不是一个NumPy ufunc,所以最终调用的是Cython函数map_infer,但是它仍然在执行您传递给Series df['a']的每个成员的任何函数,每次都是一个。
发布于 2018-07-26 14:25:48
一种简洁的方法是:
df['c'] = 2 * df['a']不需要按元素计算新列。
发布于 2018-07-26 14:31:30
你为什么要使用lambda函数?您可以轻松地完成上述任务。
df['c'] = 2 * df['a']这不会增加开销。
https://stackoverflow.com/questions/51541151
复制相似问题