【问题标题】:Vectorized implementation of a function in pandaspandas 中函数的矢量化实现
【发布时间】:2017-06-30 14:42:53
【问题描述】:

这是我目前的功能:

def partnerTransaction(main_df, ptn_code, intent, retail_unique):

    if intent == 'Frequency':
        return main_df.query('csp_code == @retail_unique & partner_code == @ptn_code')['tx_amount'].count()

    elif intent == 'Total_value':
        return main_df.query('csp_code == @retail_unique & partner_code == @ptn_code')['tx_amount'].sum()

它的作用是接受一个 Pandas DataFrame (DF 1) 和三个搜索参数。 Retail_unique 是来自另一个数据帧 (DF 2) 的字符串。目前,我使用 itertuples 遍历 DF 2 的行并调用大约 200 个这样的函数并写入第三个 DF,这只是一个示例。我在 DF 2 中有大约 16000 行,所以它非常慢。我想要做的是矢量化这个函数。我希望它返回一个熊猫系列,其中每个零售唯一的 tx_amount 计数。所以这个系列将是

34 # retail a
54 # retail b
23 # retail c

然后我会将这个系列映射到第三个 DF。

有什么想法可以解决这个问题吗?

编辑:第一个 DF 包含基于时间的数据,每个零售在一个列中出现多次,而 tx_amount 在另一列中出现,就像这样

Retail  tx_amount
retail_a  50
retail_b  100
retail_a  70
retail_c  20
retail_a  10

第二个 DF 是按零售商安排的:

Retail
retail_a
retail_b
retail_c

【问题讨论】:

    标签: python database pandas dataframe vectorization


    【解决方案1】:

    首先使用mergeleft join

    然后 groupby 按列 tx_amount 并通过 agg 函数 sizesum 一起聚合或分别在第二个解决方案中聚合。

    最后一个reset_index 用于将Series 转换为2 列DataFrame

    如果需要同时输出:

    def partnerTransaction_together(df1, df2):
        df = pd.merge(df1, df2, on='Retail', how='left')
        d = {'size':'Frequency','sum':'Total_value'}
        return df.groupby('Retail')['tx_amount'].agg(['size','sum']).rename(columns=d)
    
    print (partnerTransaction_together(df1, df2))
              Frequency  Total_value
    Retail                          
    retail_a          3          130
    retail_b          1          100
    retail_c          1           20
    

    但如果需要使用条件:

    def partnerTransaction(df1, df2, intent):
        df = pd.merge(df1, df2, on='Retail', how='left')
        g = df.groupby('Retail')['tx_amount']
    
        if intent == 'Frequency':
            return g.size().reset_index(name='Frequency')
        elif intent == 'Total_value':
            return g.sum().reset_index(name='Total_value')
    
    print (partnerTransaction(df1, df2, 'Frequency'))
         Retail  Frequency
    0  retail_a          3
    1  retail_b          1
    2  retail_c          1
    
    print (partnerTransaction(df1, df2, 'Total_value'))
         Retail  Total_value
    0  retail_a          130
    1  retail_b          100
    2  retail_c           20
    

    【讨论】:

    • 您能解释一下这是如何工作的吗?我是 Pandas 的新手,我知道您按零售对其进行分组并从中访问 tx_amount 系列。为什么要重置索引?
    • @NeevParikh,jezrael 的 agg 解决方案是最好的惯用 pandas。
    【解决方案2】:

    如果您想要速度,这里是使用bincountnumpy 解决方案

    from collections import OrderedDict
    
    f, u = pd.factorize(df1.Retail.values)
    
    c = np.bincount(f)
    s = np.bincount(f, df1.tx_amount.values).astype(df1.tx_amount.dtype)
    
    pd.DataFrame(OrderedDict(Frequency=c, Total_value=s), u)
    
              Frequency  Total_value
    retail_a          3          130
    retail_b          1          100
    retail_c          1           20
    

    时机

    df1 = pd.DataFrame(dict(
            Retail=np.random.choice(list('abcdefghijklmnopqrstuvwxyz'), 10000),
            tx_amount=np.random.randint(1000, size=10000)
        ))
    
    
    %%timeit
    f, u = pd.factorize(df1.Retail.values)
    
    c = np.bincount(f)
    s = np.bincount(f, df1.tx_amount.values).astype(df1.tx_amount.dtype)
    
    pd.DataFrame(OrderedDict(Frequency=c, Total_value=s), u)
    
    1000 loops, best of 3: 607 µs per loop
    
    
    %%timeit
    d = {'size':'Frequency','sum':'Total_value'}
    df1.groupby('Retail')['tx_amount'].agg(['size','sum']).rename(columns=d)
    
    1000 loops, best of 3: 1.53 ms per loop
    

    【讨论】:

      猜你喜欢
      • 2017-04-06
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      • 2023-03-20
      • 2022-01-08
      • 2017-02-28
      • 1970-01-01
      • 2018-06-11
      相关资源
      最近更新 更多