【问题标题】:Pandas Groupby and apply a custom function to each N- rows of a Column in that groupPandas Groupby 并将自定义函数应用于该组中列的每 N 行
【发布时间】:2019-06-26 21:04:18
【问题描述】:

我有一个 pandas 数据框,我想对一列执行 groupby 并将自定义函数应用于另一列。但该函数必须应用于 apply-column 的每两个条目。

df = pd.DataFrame({'id':[1,1,2,2,2,3,3,3,3,3], 'vals':['ANZ', 'ABC', 'SAT', 'SATYA', 'SQL', 'WER', 'DEA', 'KIP', 'FTY', 'TCZ'] })
#df
id  vals  
1   ANZ
1   ABC
2   SAT
2   SATYA
2   SQL
3   WER
3   DEA
3   KIP
3   FTY
3   TCZ
# i need a column "res", as a func applied to column vals's each two rows on a group by on column 'id'. ### myfunc takes two argument and return one value.
df['res'] = df.groupby('id')['vals'].apply(myfunc)
###df
id  vals   res
1   ANZ    myfunc(None, ANZ)
1   ABC    myfunc('ANZ', 'ABC')
2   SAT    myfunc(None, 'SAT')
2   SATYA  myfunc('SAT', 'SATYA')
2   SQL    myfunc('SATYA', 'SQL')
3   WER    myfunc(None, 'WER')
3   DEA    myfunc('WER', 'DEA')
3   KIP    myfunc('DEA', 'KIP')
3   FTY    myfunc('KIP', 'FTY')
3   TCZ    myfunc('FTY', 'TCZ')

但目前无法形成 apply() 的表达式,作为一个 group by .apply(x),x 将是一个系列,我无法找到一种方法在 x(pandas groupby 系列上使用索引访问对象)。

请指导我如何实现这一点,谢谢 Adv.

【问题讨论】:

  • 我对代码做了一点修改,请大家看看,谢谢。

标签: python pandas


【解决方案1】:

所以我尝试了类似下面的方法。

Myfunc 用于查找两个字符串之间的字符串相似度,为此我使用了很棒的模糊模糊库

from fuzzywuzzy import fuzz

def myfunc(x):
    x = x.tolist() # converted series to list
    y = []
    for i in range(0, len(x)):
        if i == 0:
            y.append(None)
        else:
            ## apply ratio between prev_Row_vals and Current_Row_vals
            y.append(fuzz.token_set_ratio(x[i - 1], x[i]) / 10)
    return y

  ## Now the group by and apply/transform function
  df['res'] = df.groupby('id')['vals'].transform(lambda x: myfunc(x))

但我不确定这是否是 Python 的方式来做这样的事情。如果有更多的pythonic方法可以做到这一点,请告诉我。谢谢。

【讨论】:

    【解决方案2】:

    我想建议以稍微不同的方式完成你的任务。

    从上一行生成带有vals 的列开始 在当前组。我将其命名为prev

    然后使用apply 调用你的函数到df 中的每一行,替换 结果做res 列。 myfunc 获取当前行并且必须提取 prevvals ,然后返回结果。

    唯一剩下的就是删除prev 列。

    所以整个脚本如下所示:

    import pandas as pd
    
    def myfunc(x):
        pr = x.prev
        t1 = pr if pd.notnull(pr) else None
        t2 = x.vals
        return f'myfunc({repr(t1)}, {repr(t2)})'
    
    df = pd.DataFrame({'id':[1,1,2,2,2,3,3,3,3,3], 'vals':
        ['ANZ', 'ABC', 'SAT', 'SATYA', 'SQL', 'WER', 'DEA', 'KIP', 'FTY', 'TCZ'] })
    df['prev'] = df.groupby('id').shift()
    df['res'] = df.apply(myfunc, axis=1)
    df.drop('prev', axis=1, inplace=True)
    

    当你print(df)时,你会得到:

       id   vals                     res
    0   1    ANZ     myfunc(None, 'ANZ')
    1   1    ABC    myfunc('ANZ', 'ABC')
    2   2    SAT     myfunc(None, 'SAT')
    3   2  SATYA  myfunc('SAT', 'SATYA')
    4   2    SQL  myfunc('SATYA', 'SQL')
    5   3    WER     myfunc(None, 'WER')
    6   3    DEA    myfunc('WER', 'DEA')
    7   3    KIP    myfunc('DEA', 'KIP')
    8   3    FTY    myfunc('KIP', 'FTY')
    9   3    TCZ    myfunc('FTY', 'TCZ')
    

    【讨论】:

      【解决方案3】:

      IIUC,你可以试试下面的;

      df['new_value']=df.vals.shift()
      df.groupby(df.index//2)['vals','new_value'].apply(lambda x: pd.Series(list(zip(x.new_value,x.vals))))\
      .stack().reset_index(drop=True)
      
      0      (nan, ANZ)
      1      (ANZ, ABC)
      2      (ABC, SAT)
      3    (SAT, SATYA)
      4    (SATYA, SQL)
      5      (SQL, WER)
      6      (WER, DEA)
      7      (DEA, KIP)
      8      (KIP, FTY)
      9      (FTY, TCZ)
      

      EDIT稍微修改代码以匹配输出:

      a=df.groupby('id')['vals'].apply(lambda x: pd.DataFrame(list(zip(x.shift(),x))))
      df['new']=list(zip(a[0],a[1]))
      print(df)
      
         id   vals           new
      0   1    ANZ    (nan, ANZ)
      1   1    ABC    (ANZ, ABC)
      2   2    SAT    (nan, SAT)
      3   2  SATYA  (SAT, SATYA)
      4   2    SQL  (SATYA, SQL)
      5   3    WER    (nan, WER)
      6   3    DEA    (WER, DEA)
      7   3    KIP    (DEA, KIP)
      8   3    FTY    (KIP, FTY)
      9   3    TCZ    (FTY, TCZ)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-01-23
        • 1970-01-01
        • 2019-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-29
        • 2022-11-24
        相关资源
        最近更新 更多