【问题标题】:Add a sequence number to each element in a group using python使用python为组中的每个元素添加一个序列号
【发布时间】:2015-06-03 20:59:57
【问题描述】:

我有一个个人数据框,每个人都有多个记录。我想为python中的每个人枚举序列中的记录。基本上我想在下表中创建“序列”列:

patient  date      sequence
145      20Jun2009        1
145      24Jun2009        2
145      15Jul2009        3
582      09Feb2008        1
582      21Feb2008        2
987      14Mar2010        1
987      02May2010        2
987      12May2010        3

这与here 本质上是同一个问题,但我在python 中工作,无法实现sql 解决方案。我怀疑我可以使用具有可迭代计数的 groupby 语句,但到目前为止还没有成功。谢谢!

【问题讨论】:

    标签: python database pandas count grouping


    【解决方案1】:

    问题是如何对多列数据进行排序。

    一个简单的技巧是将key 参数用于sorted 函数。

    您将按从数组的列构建的字符串进行排序。

    rows = ...# your source data
    
    def date_to_sortable_string(date):
      # use datetime package to convert string to sortable date.
      pass
    
    # Assume x[0] === patient_id and x[1] === encounter date
    
    # Sort by patient_id and date
    rows_sorted = sorted(rows, key=lambda x: "%0.5d-%s" % (x[0], date_to_sortable_string(x[1])))
    
    for row in rows_sorted:
      print row
    

    【讨论】:

      【解决方案2】:

      我偶然发现了一个简单得令人尴尬的答案。 groupby 语句有一个 'cumcount()' 选项,它将枚举组项目。

      df['sequence']=df.groupby('patient').cumcount()
      

      需要注意的是,记录必须按照您希望它们枚举的顺序排列。

      【讨论】:

      • 哇,真是个救命稻草——运行速度比我的任何 hack 都快
      • 谢谢!这为我节省了很多时间和挫败感。
      • .cumcount() 以 0 开头,.cumcount()+1 更有用。
      【解决方案3】:

      首先,您要将日期列转换为 pandas 日期时间(而不是字符串):

      In [11]: pd.to_datetime(df['date'], format='%d%b%Y')
      Out[11]:
      0   2009-06-20
      1   2009-06-24
      2   2009-07-15
      3   2008-02-09
      4   2008-02-21
      5   2010-03-14
      6   2010-05-02
      7   2010-05-12
      Name: date, dtype: datetime64[ns]
      

      注意:请参阅docs 了解可能的格式选项。

      In [12]: df['date'] = pd.to_datetime(df['date'], format='%d%b%Y')
      
      In [13]: df
      Out[13]:
         patient       date  sequence
      0      145 2009-06-20         1
      1      145 2009-06-24         2
      2      145 2009-07-15         3
      3      582 2008-02-09         1
      4      582 2008-02-21         2
      5      987 2010-03-14         1
      6      987 2010-05-02         2
      7      987 2010-05-12         3
      

      如果这不是按日期顺序(针对每个患者),我会先对其进行排序:

      In [14]: df = df.sort('date')
      

      现在您可以 groupby 和 cumcount:

      In [15]: g = df.groupby('patient')
      
      In [16]: g.cumcount() + 1
      Out[16]:
      2    1
      3    2
      0    1
      1    2
      4    1
      5    2
      6    3
      dtype: int64
      

      这是你想要的(尽管它不正常):

      In [17]: df['sequence'] = g.cumcount() + 1
      
      In [18]: df
      Out[18]:
             patient       date  sequence
      2      582 2008-02-09         1
      3      582 2008-02-21         2
      0      145 2009-06-24         1
      1      145 2009-07-15         2
      4      987 2010-03-14         1
      5      987 2010-05-02         2
      6      987 2010-05-12         3
      

      要重新排列(尽管您可能不需要)使用sort_index(或者如果我们保存了初始 DataFrame 的索引,我们可以重新索引):*

      In [19]: df.sort_index()
      Out[19]:
         patient       date  sequence
      0      145 2009-06-24         1
      1      145 2009-07-15         2
      2      582 2008-02-09         1
      3      582 2008-02-21         2
      4      987 2010-03-14         1
      5      987 2010-05-02         2
      6      987 2010-05-12         3
      

      【讨论】:

        【解决方案4】:

        这将从 1 而不是 0 开始排序。

        df['sequence']=df.groupby('patient').cumcount()+1
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-08
          • 2017-03-05
          • 1970-01-01
          • 1970-01-01
          • 2019-02-16
          • 2014-06-23
          相关资源
          最近更新 更多