【问题标题】:Construct new column with first row of a groupby with two columns - Pandas用两列的 groupby 的第一行构造新列 - Pandas
【发布时间】:2019-05-27 22:55:06
【问题描述】:

我正在尝试构造一个新列,如果它是“类型”列的元素第一次具有列“xx”的特定值,则其值为 1,并在任何其他情况。

  • 我正在使用的原始数据框 (df) 是:

    idx = [np.array(['Jan-18', 'Jan-18', 'Feb-18', 'Mar-18', 'Mar-18', 'Mar-18','Apr-18', 'Apr-18', 'May-18', 'Jun-18', 'Jun-18', 'Jun-18','Jul-18', 'Aug-18', 'Aug-18', 'Sep-18', 'Sep-18', 'Oct-18','Oct-18', 'Oct-18', 'Nov-18', 'Dec-18', 'Dec-18',]),np.array(['A', 'B', 'B', 'A', 'B', 'C', 'A', 'B', 'B', 'A', 'B', 'C','A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'A', 'B', 'C'])]
    data = [{'xx': 1000}, {'xx': 1000}, {'xx': 1200}, {'xx': 800}, {'xx': 800}, {'xx': 800},{'xx': 1000}, {'xx': 1000}, {'xx': 800}, {'xx': 1200}, {'xx': 1200}, {'xx': 1200},{'xx': 1000}, {'xx': 1000}, {'xx': 1000}, {'xx': 1600}, {'xx': 1600}, {'xx': 1000}, {'xx': 800}, {'xx': 800}, {'xx': 1000}, {'xx': 1600}, {'xx': 1600}]
    df = pd.DataFrame(data, index=idx, columns=['xx'])
    df.index.names=['date','type']
    df=df.reset_index()
    df['date'] = pd.to_datetime(df['date'],format = '%b-%y')
    df=df.set_index(['date','type'])
    df['xx'] = df.xx.astype('float')
    
  • 我要找的结果是:

                         xx   yy
    date       type
    2018-01-01 A     1000.0  1.0
               B     1000.0  1.0
    2018-02-01 B     1200.0  1.0
    2018-03-01 A      800.0  1.0
               B      800.0  1.0
               C      800.0  1.0
    2018-04-01 A     1000.0  0.0
               B     1000.0  0.0
    2018-05-01 B      800.0  0.0
    2018-06-01 A     1200.0  1.0
               B     1200.0  0.0
               C     1200.0  1.0
    2018-07-01 A     1000.0  0.0
    2018-08-01 B     1000.0  0.0
               C     1000.0  1.0
    2018-09-01 A     1600.0  1.0
               B     1600.0  1.0
    2018-10-01 C     1000.0  0.0
               A      800.0  0.0
               B      800.0  0.0
    2018-11-01 A     1000.0  0.0
    2018-12-01 B     1600.0  0.0
               C     1600.0  1.0
    
  • 我尝试了以下代码,但它不起作用(它给出了错误消息):

    df['yy'] = df.assign(zz=(df.groupby(['type','xx']).first())).zz.transform(lambda x: 1)
    

错误信息说

ValueError: 传递的项目数错误 0,位置表示 1。

我尝试了其他方法,例如 nth(0),但它也不起作用。非常欢迎任何有关如何解决此问题的建议。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    试试:

    df['yy'] = (df.groupby(level=1).xx
                  .apply(lambda x: (~x.duplicated()).astype(int))
               )
    
    df['yy']
    

    输出:

    date        type
    2018-01-01  A       1
                B       1
    2018-02-01  B       1
    2018-03-01  A       1
                B       1
                C       1
    2018-04-01  A       0
                B       0
    2018-05-01  B       0
    2018-06-01  A       1
                B       0
                C       1
    2018-07-01  A       0
    2018-08-01  B       0
                C       1
    2018-09-01  A       1
                B       1
    2018-10-01  C       0
                A       0
                B       0
    2018-11-01  A       0
    2018-12-01  B       0
                C       1
    Name: yy, dtype: int32
    

    【讨论】:

    • 很好的答案.. +1 你知道你也可以使用索引标签名称吗?而不是级别= 0。我认为当你有索引标签时它更具可读性。 df['yy'] = df.groupby('type')['xx'].apply(lambda x: (~x.duplicated()).astype(int))
    • @ScottBoston 谢谢。是的,正如你提到的,我们可以做到groupby('type')
    • @QuangHoang +1。您能否解释一下符号〜在您的解决方案中的作用。谢谢
    • @MarioArend 取反,(True->False and False -> True)。
    【解决方案2】:

    使用groupby + cumcount + astype

    df['yy'] = df.reset_index().groupby(['type','xx']).cumcount().eq(0).astype(int).values
    

    结果:

                         xx  yy
    date       type            
    2018-01-01 A     1000.0   1
               B     1000.0   1
    2018-02-01 B     1200.0   1
    2018-03-01 A      800.0   1
               B      800.0   1
               C      800.0   1
    2018-04-01 A     1000.0   0
               B     1000.0   0
    2018-05-01 B      800.0   0
    2018-06-01 A     1200.0   1
               B     1200.0   0
               C     1200.0   1
    2018-07-01 A     1000.0   0
    2018-08-01 B     1000.0   0
               C     1000.0   1
    2018-09-01 A     1600.0   1
               B     1600.0   1
    2018-10-01 C     1000.0   0
               A      800.0   0
               B      800.0   0
    2018-11-01 A     1000.0   0
    2018-12-01 B     1600.0   0
               C     1600.0   1
    

    【讨论】:

    • @piRSquared 打败了我,因为结果系列有一个范围索引而不是正确的日期 intex,所以缺少“值”
    • 我以前从未注意到这一点,我觉得df.reset_index().groupby(['type','xx']).cumcount() 不会生成和索引['type', 'xx'] 作为级别。我编辑以使用values 属性进行分配。
    • 好点,好像链接序列是相反的。也许有人可以对这个问题有所了解
    • 但是,给定适当高版本的 Pandas,您可以在 groupby... 中包含 index 级别名称...所以这可以工作 df.groupby(['type', 'xx']).cumcount().eq(0)
    • df.groupby([df.index.get_level_values(1),df.xx]).xx.cumcount().eq(0).astype(int)
    【解决方案3】:

    duplicated

    • 使用typexx 生成元组列表
    • 将其包装在pandas.Series 中,因为我想使用pandas.Series.duplicated 方法
    • 使用numpy.where01 之间进行选择

    注意:这不使用groupby,因此应该更有效。


    s = pd.Series([*zip(df.index.get_level_values('type'), df.xx)])
    df.assign(id=np.where(s.duplicated(), 0, 1))
    
                         xx  id
    date       type            
    2018-01-01 A     1000.0   1
               B     1000.0   1
    2018-02-01 B     1200.0   1
    2018-03-01 A      800.0   1
               B      800.0   1
               C      800.0   1
    2018-04-01 A     1000.0   0
               B     1000.0   0
    2018-05-01 B      800.0   0
    2018-06-01 A     1200.0   1
               B     1200.0   0
               C     1200.0   1
    2018-07-01 A     1000.0   0
    2018-08-01 B     1000.0   0
               C     1000.0   1
    2018-09-01 A     1600.0   1
               B     1600.0   1
    2018-10-01 C     1000.0   0
               A      800.0   0
               B      800.0   0
    2018-11-01 A     1000.0   0
    2018-12-01 B     1600.0   0
               C     1600.0   1
    

    【讨论】:

      【解决方案4】:

      IIUC

      idx=df.groupby([df.index.get_level_values(1),df.xx]).head(1).index
      df.loc[:,'new']=0
      df.loc[idx,'new']=1
      df
      Out[869]: 
                           xx  new
      date       type             
      2018-01-01 A     1000.0    1
                 B     1000.0    1
      2018-02-01 B     1200.0    1
      2018-03-01 A      800.0    1
                 B      800.0    1
                 C      800.0    1
      2018-04-01 A     1000.0    0
                 B     1000.0    0
      2018-05-01 B      800.0    0
      2018-06-01 A     1200.0    1
                 B     1200.0    0
                 C     1200.0    1
      2018-07-01 A     1000.0    0
      2018-08-01 B     1000.0    0
                 C     1000.0    1
      2018-09-01 A     1600.0    1
                 B     1600.0    1
      2018-10-01 C     1000.0    0
                 A      800.0    0
                 B      800.0    0
      2018-11-01 A     1000.0    0
      2018-12-01 B     1600.0    0
                 C     1600.0    1
      

      【讨论】:

        猜你喜欢
        • 2016-01-21
        • 1970-01-01
        • 2021-01-06
        • 2017-06-22
        • 2023-01-17
        • 1970-01-01
        • 2018-12-26
        • 1970-01-01
        • 2018-09-01
        相关资源
        最近更新 更多