有很多方法可以在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
答案 0 :(得分:3)
一种简洁的方法是:
df['c'] = 2 * df['a']
无需逐元素计算新列。
答案 1 :(得分:3)
简短的回答:矢量化调用(df['c'] = 2 * df['a']
)几乎总是在速度和可读性上取胜。有关在性能方面可以用作选项的“层次结构”的信息,请参见this答案。
通常,如果您在Pandas操作的某处存在for i in ...
或lambda
,这(有时)意味着结果计算将调用 Python 代码,而不是熊猫的Cython库用于矢量化操作的优化C代码。 (对于依赖于基础.values
的NumPy函数的操作也是如此。)
对于.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()
:顾名思义,通常当您想为Series提供 mapping 时(虽然可以像在您的代码中那样传递函数),您会看到此信息题)。这并不意味着它不是高性能的,只是在我见过的情况下它往往被用作一种专门的方法:
>>> df['a'].map(dict(enumerate('xyz', 1)))
0 x
1 y
2 z
Name: a, dtype: object
对于.apply()
:要在答案中注入一点意见,我认为在可能的情况下使用向量化会更加惯用。您可以在module where .apply()
is defined的代码中看到:由于您传递的是lambda而不是NumPy ufunc,因此最终被称为的是Cython函数map_infer
,但它仍然可以执行您所需要的任何功能一次传给df['a']
系列的每个成员。
答案 2 :(得分:0)
为什么要使用lambda函数? 您可以通过
轻松地完成上述任务df['c'] = 2 * df['a']
这不会增加开销。