我的数据如下:
ID my_val db_val
a X X
a X X
a Y X
b X Y
b Y Y
b Y Y
c Z X
c X X
c Z X
预期结果:
ID my_val db match
a X:2;Y:1 X full_match
b Y:2;X:1 Y full_match
c z:2;X:1 X partial_match
full_match是db_val与最丰富的my_val匹配时 当db_val在其他值中但与顶部值不匹配时,partial_match是。
我目前的方法是按ID分组,然后将值计数到一个单独的列中,然后将值及其计数串联在一起,然后将每个ID的所有值汇总到一行中。
这是我汇总列的方式:
def all_hits_aggregate_df(df, columns=['my_val']):
grouped = data.groupby('ID')
l=[]
for c in columns:
res = grouped[c].value_counts(ascending=False, normalize=False).to_frame('count_'+c).reset_index(level=1)
res[c] = res[c].astype(str) +':'+ res['count_'+c].astype(str)
l.append(res.groupby('ID').agg(lambda x: ';'.join(x)))
return reduce(lambda x, y: pd.merge(x, y, on = 'ID'), l)
在比较阶段,我遍历每一行并将my_val列解析为列表,然后进行比较。
我确定比较步骤的效率极低,但是我不确定在聚合之前如何进行此操作,以避免稍后在过程中解析生成的字符串。
答案 0 :(得分:2)
我们可以按ID groupby
来使用DataFrame,然后使用my_val
来计数value_counts
的值,并使用to_json
转换为json,这在格式上进行了一些小的更改后,我们要求的格式(我们只需要删除大括号和引号,并用分号替换逗号)。在分组的数据上,我们还取first
的{{1}}(大概是每个ID
的唯一值)并计算匹配百分比(超过50%的匹配项将得出{{1 }},0-50%是db_val
,0%是full_match
):
partial_match
输出:
no_match
答案 1 :(得分:0)
这应该为您提供所需的第一部分:
df['equal'] = df.my_val == df.db_val
df2 = pd.DataFrame()
df2['my_val'] = df.groupby('ID')['my_val'].sum()
df2['db'] = df.groupby('ID')['db_val'].unique()
df2['match_val'] = df.groupby('ID')['equal'].sum()
df2['match'] = ''
df2.loc[df2.match_val/len(df2.my_val) > 0.5, 'match'] = 'full_match'
df2.loc[df2.match_val/len(df2.my_val) <= 0.5, 'match'] = 'partial_match'
df2.loc[df2.match_val/len(df2.my_val) == 0, 'match'] = 'no_match'
df2 = df2.drop(columns = 'match_val')
print(df2)
my_val db match
ID
a XXY [X] full_match
b XYY [Y] full_match
c ZXZ [X] partial_match