【问题标题】:how to do Transpose function in pandas Data Frame如何在熊猫数据框中执行转置功能
【发布时间】:2021-09-03 04:26:27
【问题描述】:

我是 python 新手,所以请帮助我。

我有一个数据框

df

        id    status     emailaddress  ownername   Key   
        a     pending    a.gmail.com   as          1
        a     pending     a.gmail.com   as         2
        a     submitted   a.gmail.com   as         3
        a     submitted   a.gmail.com   as         4
        b     pending    b.gmail.com    bs         1
        b     pending     b.gmail.com   bs         2
        b     pending     b.gmail.com   bs         3
        b     pending     b.gmail.com   bs         4
        b     pending    b.gmail.com    bs         1
        c     submitted   c.gmail.com   bs         1
        c     submitted   c.gmail.com   bs         3
        c     submitted   c.gmail.com   bs         4

我想根据每个 id 的状态计算 Key 列的计数。

此外,如果状态任何一个状态 = 未决,则该用户的整体状态将在摘要表中处于未决状态。

Total Key = count (Key) where status(pending)

CompletedKey = count (Key) where status(submitted)

预期的 df_summary

        id    status     emailaddress  ownername   TotalKey   CompletedKey  RemainingKey   
        a      pending    a.gmail.com   as         4           2              2
        b      pending    b.gmail.com   bs         5           0              4
        c      submitted  c.gmail.com   cs         3           3              0
        

我的代码

    dfResponse = df.groupby(['id','ownername','status','emailaddress'])['Key'].count().reset_index(name="TotalKey")     

【问题讨论】:

    标签: pandas dataframe


    【解决方案1】:

    使用agg 计算计数器并与您的原始数据框合并。要保持正确的状态,请创建一个有序的分类 dtype,以确保在对值进行排序时首先出现 pending 状态。

    >>> df.astype({'status': pd.CategoricalDtype(['pending', 'submitted'], ordered=True)}) \
          .merge(df.groupby('id')
                   .agg(TotalKey=('Key', 'count'),
                        CompletedKey=('status', lambda x: sum(x == 'submitted')), 
                        RemainingKey=('status', lambda x: sum(x == 'pending'))),
                 on='id') \
          .sort_values('status') \
          .drop_duplicates('id') \
          .drop(columns='Key')
    
    
      id     status emailaddress ownername  TotalKey  CompletedKey  RemainingKey
    0  a    pending  a.gmail.com        as         4             2             2
    4  b    pending  b.gmail.com        bs         5             0             5
    9  c  submitted  c.gmail.com        bs         3             3             0
    

    【讨论】:

      【解决方案2】:

      使用assign 为您要执行的不同Key 列创建布尔列,然后您可以在groupby 之后使用sum。对于状态列,保持where 挂起并在groupby 之后使用first 来获取值挂起,当至少有一个在组中时,然后fillna 通过提交缺少状态 - 因为如果没有,那么只有提交给这个组。

      dfResponse = (
          df.assign(
              TotalKey=True, 
              CompletedKey=lambda x: x['status'].eq('submitted'),
              RemainingKey=lambda x: ~x['CompletedKey'], # assuming it is either submitted or pending
              status=lambda x: x['status'].where(x['RemainingKey'])) # keep only the pending values
            .groupby(['id','ownername','emailaddress']) # remove status from groupby
            .agg({'status':'first', # get pending if any pending in the group
                  'TotalKey':sum, # sum because these columns are boolean
                  'CompletedKey':sum,
                  'RemainingKey':sum})
            .fillna({'status':'submitted'}) # fill missing status when no pending
            .reset_index()
      )
      
      print(dfResponse)
        id ownername emailaddress     status  TotalKey  CompletedKey  RemainingKey
      0  a        as  a.gmail.com    pending         4             2             2
      1  b        bs  b.gmail.com    pending         5             0             5
      2  c        bs  c.gmail.com  submitted         3             3             0
      

      【讨论】:

      • 您可以在一个agg 操作中简化assignagg,不是吗?
      • @Corralien 是的,我同意,我先走这条路,因为我没有看到状态列的要求,并且使用 assign 是一种直接在所有关键列上执行 groupby.sum 的方法.一旦添加了状态列,它就不再是最好的了..
      【解决方案3】:

      您可以结合.groupby(确定每个待处理/提交组的计数)+.pivot_table(重塑/求和数据帧):

      x = df.groupby(["id", "status"], as_index=False).agg(
          {
              "status": "first",
              "emailaddress": "first",
              "ownername": "first",
              "Key": "count",
          }
      )
      x = x.pivot_table(
          index=["id", "emailaddress", "ownername", "status"],
          columns="status",
          aggfunc="sum",
      )
      x.columns = x.columns.map("_".join)
      x = (
          x.rename(
              columns={"Key_pending": "RemainingKey", "Key_submitted": "CompletedKey"}
          )
          .fillna(0)
          .astype(int)
      )
      x["TotalKey"] = x.sum(1)
      print(x.reset_index().sort_values(["id", "status"]).drop_duplicates("id"))
      

      打印:

        id emailaddress ownername     status  RemainingKey  CompletedKey  TotalKey
      0  a  a.gmail.com        as    pending             2             0         2
      2  b  b.gmail.com        bs    pending             5             0         5
      3  c  c.gmail.com        bs  submitted             0             3         3
      

      【讨论】:

      • @Ben.T 完成。 :)
      猜你喜欢
      • 1970-01-01
      • 2022-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-02
      • 1970-01-01
      • 2017-09-09
      • 2020-02-24
      相关资源
      最近更新 更多