Python 将函数应用于Dask中的分组数据帧:如何将分组数据帧指定为函数中的参数?

Python 将函数应用于Dask中的分组数据帧:如何将分组数据帧指定为函数中的参数?,python,pandas,dask,Python,Pandas,Dask,我有一个dask数据帧,按索引(first\u name)分组 (显然,实体在现实生活中是几千行) 我想对每个分组的数据帧应用一个用户定义的函数。我想将每一行与组中的所有其他行进行比较(类似于) 以下是我尝试应用的函数: def contraster(x, DF): matches = DF.apply(lambda row: fuzz.partial_ratio(row['last_name'], x) >= 50, axis = 1) return [i for i,

我有一个
dask数据帧
,按索引(
first\u name
)分组

(显然,
实体
在现实生活中是几千行)

我想对每个分组的数据帧应用一个用户定义的函数。我想将每一行与组中的所有其他行进行比较(类似于)

以下是我尝试应用的函数:

def contraster(x, DF):
    matches = DF.apply(lambda row: fuzz.partial_ratio(row['last_name'], x) >= 50, axis = 1) 
    return [i for i, x in enumerate(matches) if x]
对于测试
实体
数据框,您可以像往常一样应用该功能:

entities.apply(lambda row: contraster(row['last_name'], entities), axis =1)
预期结果是:

Out[35]: 
0    [0, 4]
1    [1, 5]
2       [2]
3       [3]
4    [0, 4]
5    [1, 5]
dtype: object
实体
庞大时,解决方案是使用
dask
。请注意,
contracter
函数中的
DF
必须是分组数据帧

def func(df, x=None):
    # do whatever you want here
    # the input to this function will have all the same first name
    return pd.DataFrame({'x': [x] * len(df),
                         'count': len(df),
                         'first_name': df.first_name})
我尝试使用以下方法:

df.groupby('first_name').apply(func=contraster, args=????)

但是我应该如何指定分组数据帧(即
对比器中的
DF

您提供给groupby应用程序的函数应该以熊猫数据帧或序列作为输入,理想情况下返回一个(或标量值)作为输出。额外的参数可以,但它们应该是次要的,而不是第一个参数。这在Pandas和Dask数据帧中都是相同的

def func(df, x=None):
    # do whatever you want here
    # the input to this function will have all the same first name
    return pd.DataFrame({'x': [x] * len(df),
                         'count': len(df),
                         'first_name': df.first_name})
然后,您可以正常调用df.groupby

import pandas as pd
import dask.dataframe as dd

df = pd.DataFrame({'first_name':['Alice', 'Alice', 'Bob'],
                   'last_name': ['Adams', 'Jones', 'Smith']})

ddf = dd.from_pandas(df, npartitions=2)

ddf.groupby('first_name').apply(func, x=3).compute()
这将在pandas或dask.dataframe中产生相同的输出

   count first_name  x
0      2      Alice  3
1      2      Alice  3
2      1        Bob  3

通过一点猜测,我认为以下是你想要的

def mapper(d):

    def contraster(x, DF=d):
        matches = DF.apply(lambda row: fuzz.partial_ratio(row['last_name'], x) >= 50, axis = 1)
        return [d.ID.iloc[i] for i, x in enumerate(matches) if x]
    d['out'] = d.apply(lambda row: 
        contraster(row['last_name']), axis =1)
    return d

df.groupby('first_name').apply(mapper).compute()
应用于您的数据,您可以得到:

   ID first_name  last_name   out
2   X      Danae      Smith   [X]
4  12      Jacke       Toro  [12]
0   X       Jake   Del Toro   [X]
1   U       John     Foster   [U]
5  13        Jon    Froster  [13]
3   Y    Beatriz  Patterson   [Y]
i、 例如,因为您按名字进行分组,所以每个组只包含一个项目,该项目只与自身匹配

但是,如果您有多行中的一些first_name值,您将获得匹配项:

entities = pd.DataFrame(
    {'first_name':['Jake','Jake', 'Jake', 'John'],
     'last_name': ['Del Toro', 'Toro', 'Smith'
                   'Froster'],
     'ID':['Z','U','X','Y']})
输出:

  ID first_name last_name     out
0  Z       Jake  Del Toro  [Z, U]
1  U       Jake      Toro  [Z, U]
2  X       Jake     Smith     [X]
3  Y       John   Froster     [Y]

如果您不需要在第一个\u名称上进行精确匹配,则可能需要按第一个\u名称排序/设置索引,并以类似方式使用
映射分区
。在这种情况下,您需要修改您的问题。

您好,您能提供一个
实体的示例吗
?我刚刚编辑了这个问题。再次感谢@mortysportyHi。请你澄清一下。。。当您按第一个名称分组时。这样做的目的是什么?例如,如果您有1000名姓简的人,他们的姓氏不同且相似,您希望得到什么样的结果?你想比较每个人都有相同的名字和相似的姓氏吗?我试图解决的问题是“重复数据消除”这一特殊类型的“记录链接”。将所有行与二次生长的所有行进行比较。所以这是不可行的。标准方法是“分块”,即将记录分块,只在块内进行比较。为了这个问题,一个精确列的块是一种简化。你能把实体变成一个全局变量吗?使用apply时,您不需要传递任何信息。如果我尝试运行您的示例,则会出现以下错误:
--------------------------------------------------------------------------------------TypeError Traceback(最近一次调用)in()7 ddf=dd.from_pandas(df,npartitions=2)8-->9 ddf.groupby('first_name').apply(func,x=3)。compute()类型错误:apply()得到一个意外的关键字参数“x”
请尝试升级到daskI的较新版本。我运行的是dask的最新版本(
0.17.2
),上面的代码在0.17.2上对我来说很好。您可能会在导致故障的最小环境中引发问题。我已经验证了在干净的安装环境下可以正常工作。我使用conda install-n myenv dask=0.17.2 ipython创建了一个新环境,并获得了所需的结果。谢谢!,这是正确的答案。很抱歉,我已经指定了赏金。