python-Pandas 数据框中的 GroupBy,得分对应于列中的出现

GroupBy in a python-Pandas dataframe with score corresponding to occurence in columns

我有一个我所在城市的数据框,其中包含人们对邻里问题的评估,看起来像这样:

personID hood problems                               problemTop1 problemTop2 problemTop3 other columns
0001     A    ['cars', 'air', 'trash', 'parks', ...] 'trash'     'cars'      'air'       ...
0002     D    ['cars', 'air', 'trash', 'parks', ...] 'cars'      'air'       'trash'     ...
0003     A    ['cars', 'air', 'trash', 'parks', ...] 'cars'      'parks'     'air'       ...
0004     M    ['cars', 'air', 'trash', 'parks', ...] 'parks'     'cars'      'air'       ...
...

Here 是数据框的简短版本,只有重要的列。我想按社区 (hood) 对数据框进行分组,并给每个可能的问题打分。分数应该是人们认为问题有多严重的加权总和,作为一个例子应该是这样的——如果在 E 附近,10 个人认为 trashproblemTop1,那么 7 个人认为problemTop2 和 3 为 problemTop3,然后

E_score_trash = 10*3 + 7*2 + 3*1 = 47

我的最终输出应该显示每个社区每个问题的分数,如下所示:

>>> df_scores_by_hood
hood 'air' 'cars' 'parks' 'trash'
A     386   871    321     984
B     436   719    504     620
C     383   230    848     601
D     881   524    231     783
...

是否有使用 pandas、numpy 或其他函数的简单方法?发送

编辑

原题没完全看懂,所以一开始答错了。这个

problems =  {'problemTop1':10,'problemTop2':7, 'problemTop3':3}
agg_df = pd.DataFrame()
for problem in problems:
    temp = pd.crosstab(df['hood'],df[problem],colnames=['problem'])
    temp = temp*problems[problem]
    agg_df = agg_df.add(temp,fill_value=0)
agg_df.astype(int)

应该以高效的方式完成任务。


原创

您需要按

展开列表列
df = df.explode('problems')

然后你可以做一个交叉表,或者根据我的经验,最好执行双 groupby 和 unstack。

df_scores_by_hood = df.groupby(['hood','problems'])['personID'].count().unstack()

我找到了一个解决方案,但我对它并不满意 - 它不是真正的 pandasic,它不是矢量化的(它有循环)而且我觉得应该有一些更简单的方法来解决我的问题。你知道如何改进吗?

# list of all the problems
problems = ['cars', 'air', 'trash',...]

for problem in problems:
    df[problem] = 0
    df[problem] = df.apply(lambda row: 3 if row['problemTop1']==problem
                           else 2 if row['problemTop2']==problem
                           else 1 if row['problemTop3']==problem
                           else 0, axis=1)