我怎样才能优化这个多数票

Posted

技术标签:

【中文标题】我怎样才能优化这个多数票【英文标题】:How can I optimize this majority vote 【发布时间】:2021-04-30 21:07:48 【问题描述】:

我有以下代码对数据框中的数据进行多数投票:

def vote(df, systems):
    test = df.drop_duplicates(subset=['begin', 'end', 'case', 'system'])
    n = int(len(systems)/2)
    data = []
        
    for row in test.itertuples():
        # get all matches
        fx = test.loc[(test.begin == row.begin) & (test.end == row.end) & (test.case == row.case)]
        fx = fx.loc[fx.system.isin(systems)]

        # keep if in a majority of systems   
        if len(set(fx.system.tolist())) > n:
            data.append(fx)
             
    out = pd.concat(data, axis=0, ignore_index=True)
    out = out.drop_duplicates(subset=['begin', 'end', 'case'])
    
    return out[['begin', 'end', 'case']]  

数据如下:

systems = ['A', 'B', 'C', 'D', 'E']

df = begin,end,system,case
0,9,A,0365
10,14,A,0365
10,14,B,0365
10,14,C,0365
28,37,A,0366
38,42,A,0366
38,42,B,0366
53,69,C,0366
56,60,B,0366
56,60,C,0366
56,69,D,0366
64,69,E,0366
83,86,B,0367

预期的输出应该是:

out = begin,end,case
    10,14,0365
    56,69,0366

IOW,如果需要的元素 begin, end, case 出现在大多数系统中,我们会将它们累积并作为数据帧返回。

该算法运行良好,但由于其中有数十万行,这需要相当长的时间来处理。

我能想到的一个优化,但不确定如何实现是在itertuples 迭代中:如果对于过滤器集begin, end, case 的第一个实例有匹配项

fx = test.loc[(test.begin == row.begin) & (test.end == row.end) & (test.case == df.case) & (fx.system.isin(systems))]

那么,最好不要迭代 itertuples 可迭代中与此过滤器匹配的其他行。例如,对于10,14,A,0365 的第一个实例,不需要检查接下来的两行,因为它们已经被评估过。但是,由于 iterable 已经固定,因此无法跳过我能想到的这些。

【问题讨论】:

我觉得这个问题更适合code review 谢谢,我正在考虑是否将它发布到那里。 还有一件事,该功能不适用于共享的虚拟数据。请修复它:) fx.system.isin(systems)) 也许 您能否提供更多数据,这些数据可能与当前的 dtaa 有不同的系统?只是想测试解决方案 【参考方案1】:

我猜这就是你要找的,

import pandas as pd
from io import StringIO

#Preprocessing(ignore)
data = StringIO('''
0,9,A,0365
10,14,A,0365
10,14,B,0365
10,14,C,0365
28,37,A,0366
38,42,A,0366
38,42,B,0366
53,69,C,0366
56,60,B,0366
56,60,C,0366
56,69,D,0366
64,69,E,0366
83,86,B,0367
''')

systems = ['A', 'B', 'C', 'D', 'E']
df = pd.read_csv(data,names=['begin','end','system','case'])

df_test = df.drop_duplicates(subset=['begin', 'end', 'case', 'system'])[df['system'].isin(systems)]
n = int(len(systems)/2)

out = df_test.groupby(['begin']).agg(
    'end':'max',
    'case':'max',
    'system': 'count'
).reset_index()

out[out['system'] > n][['begin', 'end', 'case']]

输出:

begin   end case
1   10  14  365
5   56  69  366

【讨论】:

【参考方案2】:

将其移至 codereview...(不想删除它并失去声誉积分!)

【讨论】:

以上是关于我怎样才能优化这个多数票的主要内容,如果未能解决你的问题,请参考以下文章

我怎样才能优化这个mysql查询?我使用 OR 运算符

我怎样才能优化视图oracle sql

如何做优化,UITabelView才能更加顺滑

我怎样才能优化这个脚本,这样它就不需要一周的时间来完成它正在做的任务? (也使用了 BASH PARALLEL。)

关于浏览器性能优化-转

为什么要做搜索引擎优化?厉害了,好处原来这么多!