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 个人认为 trash
是 problemTop1
,那么 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)
我有一个我所在城市的数据框,其中包含人们对邻里问题的评估,看起来像这样:
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 个人认为 trash
是 problemTop1
,那么 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)