我有一个pandas数据框,我想基于现有列和某些不等式创建一个新列。例如,让
df=pd.DataFrame({'a':[1,2,3,4,5,6,7],'b':[3,6,4,2,7,7,1]})
所以df
看起来像
a b
0 1 3
1 2 6
2 3 4
3 4 2
4 5 7
5 6 7
6 7 1
我想添加一个新列res
,如果a
中的对应值小于2则等于0,如果a
中的对应值至少为1 2小于4,否则为2。所以我想得到
a b res
0 1 3 0
1 2 6 1
2 3 4 1
3 4 2 2
4 5 7 2
5 6 7 2
6 7 1 2
到目前为止,我一直使用apply
执行此操作,如下所示:
def f(x):
if x['a']<2:
return 0
elif x['a']>=2 and x['a']<4:
return 1
else:
return 2
df['res']=df.apply(f,axis=1)
但我想知道是否有更直接的方法,或者某些特定的熊猫方法可以让我这样做。
答案 0 :(得分:5)
您可以使用pd.cut
:
GridContextMenu<Project> contextMenu = new GridContextMenu<>(treeGrid);
contextMenu.addGridBodyContextMenuListener(contextEvent -> {
contextMenu.removeItems();
if (contextEvent.getItem() != null) {
Project project = (Project) contextEvent.getItem();
// update selection
treeGrid.select(project);
// show option for expanding
contextMenu.addItem("Expand all", VaadinIcons.PLUS, event -> treeGrid.expand((project).flatten().collect(Collectors.toList())));
// show option for collapsing
contextMenu.addItem("Collapse all", VaadinIcons.MINUS, event -> treeGrid.collapse((project).flatten().collect(Collectors.toList())));
}
});
输出:
df['res'] = pd.cut(df.a,[-np.inf,2,4,np.inf],labels=[0,1,2],right=False)
答案 1 :(得分:3)
只需几个值,您还可以使用numpy.where
作为矢量化解决方案:
df['res'] = pd.np.where(df.a < 2, 0, pd.np.where((df.a >= 2) & (df.a < 4), 1, 2))
df
# a b res
#0 1 3 0
#1 2 6 1
#2 3 4 1
#3 4 2 2
#4 5 7 2
#5 6 7 2
#6 7 1 2
答案 2 :(得分:3)
<强> searchsorted
强>
应该给你更高效的结果。与pd.cut
类似,您需要指定断点。
pandas
pd.Series.searchsorted
df.assign(res=pd.Series([2, 4]).searchsorted(df.a, side='right'))
a b res
0 1 3 0
1 2 6 1
2 3 4 1
3 4 2 2
4 5 7 2
5 6 7 2
6 7 1 2
numpy
ndarray.searchsorted
df.assign(res=np.array([2, 4]).searchsorted(df.a.values, side='right'))
a b res
0 1 3 0
1 2 6 1
2 3 4 1
3 4 2 2
4 5 7 2
5 6 7 2
6 7 1 2
计时
%timeit df.assign(res=pd.Series([2, 4]).searchsorted(df.a, side='right'))
%timeit df.assign(res=np.array([2, 4]).searchsorted(df.a.values, side='right'))
%timeit df.assign(res=pd.np.where(df.a < 2, 0, pd.np.where((df.a >= 2) & (df.a < 4), 1, 2)))
%timeit df.assign(res=pd.cut(df.a, [-np.inf,2,4,np.inf], labels=[0,1,2], right=False))
1000 loops, best of 3: 443 µs per loop
1000 loops, best of 3: 337 µs per loop
1000 loops, best of 3: 1.06 ms per loop
1000 loops, best of 3: 530 µs per loop