pandas

时间:2017-06-30 05:37:41

标签: python database pandas dataframe vectorization

这是我目前的职能:

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个这样的函数并写入第3个DF,这只是一个例子。我在DF 2中有大约16000行,所以它非常慢。我想要做的是矢量化这个功能。我想要它返回一个大熊猫系列,其中每个零售店的tx_amount数量都是唯一的。所以这个系列将是

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

然后我会将这个系列映射到第3个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

2 个答案:

答案 0 :(得分:2)

首先将mergeleft join一起使用。

然后groupbytx_amountagg函数sizesum汇总,或者分别汇总到第二个解决方案。

转化Series的最后reset_index到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

答案 1 :(得分:1)

如果您想要速度,请使用numpy

这是一个bincount解决方案
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