【问题标题】:Pandas modify column with groupby results while ignoring some valuesPandas 使用 groupby 结果修改列,同时忽略某些值
【发布时间】:2016-04-09 18:36:21
【问题描述】:

我正在尝试使用 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

但现在我必须将不应修改的值归零... 哦,那一定是更好的方法!

请问,我如何在一个更简单的步骤中通过忽略某些值来设置这个值?并且还请考虑到性能很重要,因为数据集有几 GB...

谢谢!

【问题讨论】:

    标签: python pandas


    【解决方案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
    

    【讨论】:

    • 谢谢你耶斯瑞尔!所以我离答案并不远,但我不知道 numpy ......无论如何,我只有一个担心:按照我的方式分配值真的安全吗,用 .values 剥离指数?是否保证两个系列的顺序相同?我需要在系列中设置一些顺序以确保它吗?如果是,请告诉我保证它的最佳方式...再次感谢!
    • 嗯,很难的问题。但是我找到了没有.values的解决方案,请检查一下。
    猜你喜欢
    • 2020-08-02
    • 1970-01-01
    • 2021-05-14
    • 2015-10-30
    • 1970-01-01
    • 2018-01-29
    • 2020-11-22
    • 2021-01-12
    • 1970-01-01
    相关资源
    最近更新 更多