我正在尝试使用Pandas使用groupby操作的结果修改庞大的数据集。 我需要的是找到数据组的最小值,同时忽略零,但如果它是组中的唯一值,则返回相同的零。
考虑这个虚拟数据:
>>> a=pd.DataFrame(dict(item_id=[1,1,1,2,2,2], pos_id=[3,7,7,7,7,7], target='T1 T2 T3 T1 T2 T3'.split(), val=[8,0,0,41,0,55]))
>>> a
item_id pos_id target val
0 1 3 T1 8
1 1 7 T2 0
2 1 7 T3 0
3 2 7 T1 41
4 2 7 T2 0
5 2 7 T3 55
对于pos_id == 7和target =='T2'中的每个item_id,我想获得整个组中最小的非零val(忽略目标),并用它代替它!
所以,我想最终得到这个:
item_id pos_id target val
0 1 3 T1 8 <-- this row has the wrong pos_id and is ignored
1 1 7 T2 0 <-- this one maintains zero (all group has zeros)
2 1 7 T3 0
3 2 7 T1 41
4 2 7 T2 41 <-- this one gets the smallest of item_id group
5 2 7 T3 55
我试过这个:
>>> a.ix[(a.pos_id == 7) & (a.target == 'T2'), 'val'] = a.ix[a.pos_id == 7].groupby('item_id').val.min().values
但它不起作用,因为零不被忽略。而且我不能简单地忽略它们,因为作业两侧的系列将有不同的大小!
>>> a.ix[(a.pos_id == 7) & (a.target == 'T2'), 'val'].size, a.ix[(a.pos_id == 7) & (a.val != 0)].groupby('item_id').val.min().values.size
(2, 1)
我也尝试在这些零中加入一个高值,所以第一个几乎会成功:
>>> a.ix[(a.pos_id == 7) & (a.val == 0), 'val'] = 9999
>>> a
item_id pos_id target val
0 1 3 T1 8
1 1 7 T2 9999
2 1 7 T3 9999
3 2 7 T1 41
4 2 7 T2 9999
5 2 7 T3 55
可是:
>>> a.ix[(a.pos_id == 7) & (a.target == 'T2'), 'val'] = a.ix[a.pos_id == 7].groupby('item_id').val.min().values
>>> a
item_id pos_id target val
0 1 3 T1 8
1 1 7 T2 9999 <-- this one should maintain zero...
2 1 7 T3 9999
3 2 7 T1 41
4 2 7 T2 41 <-- this one works!
5 2 7 T3 55
但是现在我必须将不应修改的值归还为零... 哦,它必须是更好的方式!
请问,如何在一个更简单的步骤中使用groupby忽略某些值来设置这个值?并且还请考虑性能很重要,因为数据集有几千兆字节......
谢谢!
答案 0 :(得分:1)
我认为您可以使用条件numpy.where
来检查all
值是0
,然后输出是0
否则min
没有0
使用transform
代替apply
:
a=pd.DataFrame(dict(item_id=[1,1,1,2,2,2],
pos_id=[3,7,7,7,7,7],
target='T1 T2 T3 T1 T2 T3'.split(),
val=[8,0,0,41,0,55]))
print a
item_id pos_id target val
0 1 3 T1 8
1 1 7 T2 0
2 1 7 T3 0
3 2 7 T1 41
4 2 7 T2 0
5 2 7 T3 55
a.ix[(a.pos_id == 7) & (a.target == 'T2'), 'val'] =
a.ix[a.pos_id == 7].groupby('item_id').val.transform(lambda x: np.where((x == 0).all(),
0,
x[x!=0].min()))
print a
item_id pos_id target val
0 1 3 T1 8
1 1 7 T2 0
2 1 7 T3 0
3 2 7 T1 41
4 2 7 T2 41
5 2 7 T3 55