Pandas Groupby并将自定义函数应用于该组中列的每个N行

时间:2019-02-02 14:12:21

标签: python pandas

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

a=[2,4,6]
b=[1,3,5,-1,-1,-1,-1]

def replace(iterable, replacements):
  i = 0
  for e in iterable:
    if e == -1 and i < len(replacements):
      yield replacements[i]
      i += 1
    else:
      yield e

res = sorted(replace(b, a))

print(res) #=> [-1, 1, 2, 3, 4, 5, 6]

但是目前无法形成apply()的表达式,因为.apply(x)是一个论坛,x将是一个系列,而我无法找到在x(pandas groupby series)上使用索引明智的访问方式对象)。

在广告中,请指导我如何实现此目标。

3 个答案:

答案 0 :(得分:1)

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)

编辑:略微修改代码以匹配输出:

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)

答案 1 :(得分:1)

我想建议以其他方式来完成您的任务。

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

然后使用apply调用函数df中的每一行,替换为 结果在res列中。 myfunc获取当前行,并且具有到提取prev,并 vals,然后返回结果。

剩下的唯一事情就是删除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')

答案 2 :(得分:0)

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

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

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方式。请让我知道是否还有更多的Python方式可以做到这一点。谢谢。