【问题标题】:Python Pandas: Assign Last Value of DataFrame Group to All Entries of That GroupPython Pandas:将 DataFrame 组的最后一个值分配给该组的所有条目
【发布时间】:2018-06-04 02:20:48
【问题描述】:

在 Python Pandas 中,我有一个 DataFrame。我按一列对这个 DataFrame 进行分组,并希望将一列的最后一个值分配给另一列的所有行。

我知道我可以通过这个命令选择组的最后一行:

import pandas as pd

df = pd.DataFrame({'a': (1,1,2,3,3), 'b':(20,21,30,40,41)})
print(df)
print("-")
result = df.groupby('a').nth(-1)
print(result)

结果:

   a   b
0  1  20
1  1  21
2  2  30
3  3  40
4  3  41
-
    b
a    
1  21
2  30
3  41

如何将此操作的结果分配回原始数据帧,以便我有类似的东西:

   a   b b_new
0  1  20 21
1  1  21 21
2  2  30 30
3  3  40 41
4  3  41 41

【问题讨论】:

    标签: python pandas dataframe group-by pandas-groupby


    【解决方案1】:

    transformlast 一起使用:

    df['b_new'] = df.groupby('a')['b'].transform('last')
    

    替代方案:

    df['b_new'] = df.groupby('a')['b'].transform(lambda x: x.iat[-1])
    
    print(df)
       a   b  b_new
    0  1  20     21
    1  1  21     21
    2  2  30     30
    3  3  40     41
    4  3  41     41
    

    nthjoin 的解决方案:

    df = df.join(df.groupby('a')['b'].nth(-1).rename('b_new'), 'a')
    print(df)
       a   b  b_new
    0  1  20     21
    1  1  21     21
    2  2  30     30
    3  3  40     41
    4  3  41     41
    

    时间安排

    N = 10000
    
    df = pd.DataFrame({'a':np.random.randint(1000,size=N),
                       'b':np.random.randint(10000,size=N)})
    
    #print (df)
    
    
    def f(df):
        return df.join(df.groupby('a')['b'].nth(-1).rename('b_new'), 'a')
    
    #cᴏʟᴅsᴘᴇᴇᴅ1
    In [211]: %timeit df['b_new'] = df.a.map(df.groupby('a').b.nth(-1))
    100 loops, best of 3: 3.57 ms per loop
    
    #cᴏʟᴅsᴘᴇᴇᴅ2
    In [212]: %timeit df['b_new'] = df.a.replace(df.groupby('a').b.nth(-1))
    10 loops, best of 3: 71.3 ms per loop
    
    #jezrael1
    In [213]: %timeit df['b_new'] = df.groupby('a')['b'].transform('last')
    1000 loops, best of 3: 1.82 ms per loop
    
    #jezrael2
    In [214]: %timeit df['b_new'] = df.groupby('a')['b'].transform(lambda x: x.iat[-1])
    10 loops, best of 3: 178 ms per loop
        
    #jezrael3
    In [219]: %timeit f(df)
    100 loops, best of 3: 3.63 ms per loop
    

    警告

    考虑到组的数量,结果并未解决性能问题,这将对其中一些解决方案的时间产生很大影响。

    【讨论】:

      【解决方案2】:

      两种可能,groupby + nth + mapreplace

      df['b_new'] = df.a.map(df.groupby('a').b.nth(-1))
      

      或者,

      df['b_new'] = df.a.replace(df.groupby('a').b.nth(-1))
      

      您也可以将nth(-1) 替换为last()(事实上,这样做恰好会使这更快一点),但是nth 让您可以更灵活地从b 的每个组中选择什么项目。


      df
      
         a   b  b_new
      0  1  20     21
      1  1  21     21
      2  2  30     30
      3  3  40     41
      4  3  41     41
      

      【讨论】:

        【解决方案3】:

        我认为这应该很快

        df.merge(df.drop_duplicates('a',keep='last'),on='a',how='left')
        Out[797]: 
           a  b_x  b_y
        0  1   20   21
        1  1   21   21
        2  2   30   30
        3  3   40   41
        4  3   41   41
        

        【讨论】:

          猜你喜欢
          • 2021-04-12
          • 1970-01-01
          • 2022-10-25
          • 1970-01-01
          • 2021-08-15
          • 2018-08-23
          • 1970-01-01
          • 2016-01-18
          • 2016-07-03
          相关资源
          最近更新 更多