在 pandas 数据帧中向量化条件赋值
vectorize conditional assignment in pandas dataframe
如果我有一个包含列 x
的数据框 df
并且想根据 x
的值创建列 y
在伪代码中使用:
if df['x'] < -2 then df['y'] = 1
else if df['x'] > 2 then df['y'] = -1
else df['y'] = 0
我将如何实现这一目标?我认为 np.where
是执行此操作的最佳方法,但不确定如何正确编码。
一个简单的方法是先分配默认值,然后执行 2 loc
次调用:
In [66]:
df = pd.DataFrame({'x':[0,-3,5,-1,1]})
df
Out[66]:
x
0 0
1 -3
2 5
3 -1
4 1
In [69]:
df['y'] = 0
df.loc[df['x'] < -2, 'y'] = 1
df.loc[df['x'] > 2, 'y'] = -1
df
Out[69]:
x y
0 0 0
1 -3 1
2 5 -1
3 -1 0
4 1 0
如果你想使用 np.where
那么你可以使用嵌套的 np.where
:
In [77]:
df['y'] = np.where(df['x'] < -2 , 1, np.where(df['x'] > 2, -1, 0))
df
Out[77]:
x y
0 0 0
1 -3 1
2 5 -1
3 -1 0
4 1 0
所以这里我们将第一个条件定义为 x 小于 -2,return 1,然后我们有另一个 np.where
测试 x 大于 2 和 returns -1,否则return 0
计时
In [79]:
%timeit df['y'] = np.where(df['x'] < -2 , 1, np.where(df['x'] > 2, -1, 0))
1000 loops, best of 3: 1.79 ms per loop
In [81]:
%%timeit
df['y'] = 0
df.loc[df['x'] < -2, 'y'] = 1
df.loc[df['x'] > 2, 'y'] = -1
100 loops, best of 3: 3.27 ms per loop
所以对于这个示例数据集,np.where
方法的速度是原来的两倍
这是 pd.cut
的一个很好的用例,您可以在其中定义范围并根据这些 ranges
您可以分配 labels
:
df['y'] = pd.cut(df['x'], [-np.inf, -2, 2, np.inf], labels=[1, 0, -1], right=False)
输出
x y
0 0 0
1 -3 1
2 5 -1
3 -1 0
4 1 0
对多个条件使用np.select
np.select(condlist, choicelist, default=0)
- Return elements in
choicelist
depending on the corresponding condition in condlist
.
- The
default
element is used when all conditions evaluate to False
.
condlist = [
df['x'] < -2,
df['x'] > 2,
]
choicelist = [
1,
-1,
]
df['y'] = np.select(condlist, choicelist, default=0)
np.select
比嵌套的 np.where
更易读,但同样快:
df = pd.DataFrame({'x': np.random.randint(-5, 5, size=n)})
如果我有一个包含列 x
的数据框 df
并且想根据 x
的值创建列 y
在伪代码中使用:
if df['x'] < -2 then df['y'] = 1
else if df['x'] > 2 then df['y'] = -1
else df['y'] = 0
我将如何实现这一目标?我认为 np.where
是执行此操作的最佳方法,但不确定如何正确编码。
一个简单的方法是先分配默认值,然后执行 2 loc
次调用:
In [66]:
df = pd.DataFrame({'x':[0,-3,5,-1,1]})
df
Out[66]:
x
0 0
1 -3
2 5
3 -1
4 1
In [69]:
df['y'] = 0
df.loc[df['x'] < -2, 'y'] = 1
df.loc[df['x'] > 2, 'y'] = -1
df
Out[69]:
x y
0 0 0
1 -3 1
2 5 -1
3 -1 0
4 1 0
如果你想使用 np.where
那么你可以使用嵌套的 np.where
:
In [77]:
df['y'] = np.where(df['x'] < -2 , 1, np.where(df['x'] > 2, -1, 0))
df
Out[77]:
x y
0 0 0
1 -3 1
2 5 -1
3 -1 0
4 1 0
所以这里我们将第一个条件定义为 x 小于 -2,return 1,然后我们有另一个 np.where
测试 x 大于 2 和 returns -1,否则return 0
计时
In [79]:
%timeit df['y'] = np.where(df['x'] < -2 , 1, np.where(df['x'] > 2, -1, 0))
1000 loops, best of 3: 1.79 ms per loop
In [81]:
%%timeit
df['y'] = 0
df.loc[df['x'] < -2, 'y'] = 1
df.loc[df['x'] > 2, 'y'] = -1
100 loops, best of 3: 3.27 ms per loop
所以对于这个示例数据集,np.where
方法的速度是原来的两倍
这是 pd.cut
的一个很好的用例,您可以在其中定义范围并根据这些 ranges
您可以分配 labels
:
df['y'] = pd.cut(df['x'], [-np.inf, -2, 2, np.inf], labels=[1, 0, -1], right=False)
输出
x y
0 0 0
1 -3 1
2 5 -1
3 -1 0
4 1 0
对多个条件使用np.select
np.select(condlist, choicelist, default=0)
- Return elements in
choicelist
depending on the corresponding condition incondlist
.- The
default
element is used when all conditions evaluate toFalse
.
condlist = [
df['x'] < -2,
df['x'] > 2,
]
choicelist = [
1,
-1,
]
df['y'] = np.select(condlist, choicelist, default=0)
np.select
比嵌套的 np.where
更易读,但同样快:
df = pd.DataFrame({'x': np.random.randint(-5, 5, size=n)})