避免对熊猫的每一行进行迭代以进行自定义聚合

时间:2019-03-06 21:57:37

标签: python pandas dataframe pandas-groupby

比方说,我有一个熊猫数据框架,其中有两列:salaryfood_perc(您花在食物上的薪水百分比)。每行对应一个不同的人。

import pandas as pd
import numpy as np

# Set seed
np.random.seed(1)

# Create dataframe
df = pd.DataFrame({'salary': np.round(np.random.uniform(10000, 100000, 100), 2),
                   'food_perc': np.round(np.random.uniform(0.1, 0.9, 100), 2)})

我想要一个名为food_compare的新列,其中每个人都可以看到他们的food_perc与收入相似(+/- 10%)的人的比较。

因为每个人的+/- 10%同类群组会有所不同,所以我看不出一种方法来避免遍历每一行并每次创建同类群组,如下所示。

for i in df.index:

    # Isolate the cohort
    df_sub = df[(df.loc[:, 'salary'] * 0.9 < df.loc[i, 'salary']) &
                (df.loc[:, 'salary'] * 1.1 > df.loc[i, 'salary'])]

    # Make the comparison
    df.loc[i, 'food_compare'] = np.divide(df.loc[i, 'food_perc'],
                                          np.mean(df_sub['food_perc']))

为每次迭代设置数据框实际上不是可扩展的解决方案。 不幸的是,我无法针对正在解决的问题抢先创建静态垃圾箱(例如$ 10,000- $ 20,000,$ 20,001- $ 30,000等)。

当您没有离散键时,是否可以执行某种.groupby?否则我不知道该做什么,除了可能事先通过salary对行进行排序并修改子集步骤,以便在构建同类群组时不会搜索整个数据帧。谢谢!

2 个答案:

答案 0 :(得分:4)

要获取每个对等组的计数,可以使用以下方法:

data['sal_peer_group_count'] = 
     data['salary'].apply(lambda x: len(data.loc[(data['salary']>.9*x) & 
                                       (data['salary']<1.1*x)]))

要获得sal_perc的对等组平均数

data['peer_group_food_perc_mean'] = 
     data['salary'].apply(lambda x: data.loc[(data['salary'] >.9*x) & 
                                             (data['salary'] < 1.1*x), 'food_perc'].mean())

答案 1 :(得分:1)

pd.cut是为这种事情而设计的:http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.cut.html

df.groupby(pd.cut(df["salary"], np.arange(0, df["salary"].max(), 1.0e5)))