Python 求C列的最大平均值,同时最小化A列的过滤器和B列的过滤器

Python 求C列的最大平均值,同时最小化A列的过滤器和B列的过滤器,python,performance,numpy,sorting,filter,Python,Performance,Numpy,Sorting,Filter,在过滤列A(其中A>x,x最小化)和过滤列B(其中B>y,y最小化)后,如何找到剩余列C值的最大平均值 这不是写这篇文章的正确方法,但下面是: 最小值(x)A,最小值(y)B=最大值(平均值(C)) 样本数据: 0 1 2 0 0.955264 0.018151 1.069599 1 0.250984 0.02122

在过滤列A(其中A>x,x最小化)和过滤列B(其中B>y,y最小化)后,如何找到剩余列C值的最大平均值

这不是写这篇文章的正确方法,但下面是:

最小值(x)A,最小值(y)B=最大值(平均值(C))

样本数据:

        0  1  2
0                     0.955264              0.018151                1.069599
1                     0.250984              0.021228                0.565075
2                     0.214348              0.010068                0.553522
3                     0.209648              0.005857                5.299407
4                     0.201268              0.019254               -2.655558
5                     0.180277              0.008406               -2.243170
6                     0.121976              0.012358                0.741234
7                     0.113862              0.002437               -0.459225
8                     0.094065              0.007480               -2.203349
9                     0.073183              0.002110                0.401326
10                    0.069058              0.000474               -0.565729
11                    0.059394              0.001699               -2.841782
12                    0.053492              0.000076                0.572350
13                    0.051462              0.011117               -4.751399
14                    0.044621              0.001428                1.726456
15                    0.038060              0.002472                2.900067
16                    0.035086              0.000642                2.847032
17                    0.027002              0.012311               -3.224638
18                    0.023652              0.003301               -0.401571
19                    0.017891              0.013588               -2.357813
20                    0.010771              0.003337                1.775200
21                    0.005131              0.003372                1.644813
实际数据: 行数:135269 组合:18297702361

描述这一点的最佳方法是使用下面这段极其缓慢的代码:

def process_all(df):
column_names = ['pcp1', 'pcpr1', 'alc', 'clc']
maxvalues_df = pd.DataFrame(columns = column_names)
max_leading_change = 0

for i1, r1 in df.iterrows():
    print(i1)
    cp1 = df.iloc[i1].predicted_change_percent_1
    filter_cp = df.loc[(df['pcp1'] >= cp1)]

    for i2, r2 in filter_cp.iterrows():

        cpr1 = filter_cp.iloc[i2].predicted_cpreturn_1

        filter_cpr = filter_cp.loc[(filter_cp['pcp1'] >= cpr1)]

        average_leading_change = filter_cpr['lcp'].mean()
        
        if average_leading_change > max_leading_change:

            count_leading_change = filter_cpr['lcp'].count()
            max_leading_change = average_leading_change
            max_row = {'pcp1': cp1, 'pcpr1': cpr1, 'alc': average_leading_change, 'clc': count_leading_change}
            maxvalues_df = maxvalues_df.append(max_row, ignore_index=True)
            
maxvalues_df = maxvalues_df.sort_values('alc')
return maxvalues_df
编辑:

        0  1  2
0                     0.955264              0.018151                1.069599
1                     0.250984              0.021228                0.565075
2                     0.214348              0.010068                0.553522
3                     0.209648              0.005857                5.299407
4                     0.201268              0.019254               -2.655558
5                     0.180277              0.008406               -2.243170
6                     0.121976              0.012358                0.741234
7                     0.113862              0.002437               -0.459225
8                     0.094065              0.007480               -2.203349
9                     0.073183              0.002110                0.401326
10                    0.069058              0.000474               -0.565729
11                    0.059394              0.001699               -2.841782
12                    0.053492              0.000076                0.572350
13                    0.051462              0.011117               -4.751399
14                    0.044621              0.001428                1.726456
15                    0.038060              0.002472                2.900067
16                    0.035086              0.000642                2.847032
17                    0.027002              0.012311               -3.224638
18                    0.023652              0.003301               -0.401571
19                    0.017891              0.013588               -2.357813
20                    0.010771              0.003337                1.775200
21                    0.005131              0.003372                1.644813
下面是相同的函数,但使用NumPy arras和排序。我原以为会快1000倍,但唉,只快了10倍

def process_all(df):
max_leading_change = 0
final_list = []
nump_df=df.values
#print(nump_df)

sortedArr1 = nump_df[nump_df[:,0].argsort()[::-1]]

for i1 in range(1, sortedArr1.shape[0] + 1):
    print(i1)
    filteredArr1 = sortedArr1[:i1]

    sortedArr2 = filteredArr1[filteredArr1[:,1].argsort()[::-1]]
    cp1 = filteredArr1[i1-1][0]
    
    
    for i2 in range(1, sortedArr2.shape[0] + 1):
        
        filteredArr2 = sortedArr2[:i2]
        average_leading_change = filteredArr2[:,2].mean()
                
        if average_leading_change > max_leading_change:
            cpr2 = filteredArr2[i2-1][1]
          
            # date = filteredArr2[i1-1][4]
            print(f'cp1: {cp1} | cpr2: {cpr2} | average_leading_change: {average_leading_change} | count: {i2}')
            # print(filteredArr2)
            max_leading_change = average_leading_change
            max_row = [cp1, cpr2, average_leading_change, i2]
            final_list.append(max_row) 

final_array = np.array(final_list)
# print(final_array)
return final_array
编辑2:

        0  1  2
0                     0.955264              0.018151                1.069599
1                     0.250984              0.021228                0.565075
2                     0.214348              0.010068                0.553522
3                     0.209648              0.005857                5.299407
4                     0.201268              0.019254               -2.655558
5                     0.180277              0.008406               -2.243170
6                     0.121976              0.012358                0.741234
7                     0.113862              0.002437               -0.459225
8                     0.094065              0.007480               -2.203349
9                     0.073183              0.002110                0.401326
10                    0.069058              0.000474               -0.565729
11                    0.059394              0.001699               -2.841782
12                    0.053492              0.000076                0.572350
13                    0.051462              0.011117               -4.751399
14                    0.044621              0.001428                1.726456
15                    0.038060              0.002472                2.900067
16                    0.035086              0.000642                2.847032
17                    0.027002              0.012311               -3.224638
18                    0.023652              0.003301               -0.401571
19                    0.017891              0.013588               -2.357813
20                    0.010771              0.003337                1.775200
21                    0.005131              0.003372                1.644813
我觉得这里可能有一个线性规划的解决方案,但我不熟悉线性规划

编辑3:

        0  1  2
0                     0.955264              0.018151                1.069599
1                     0.250984              0.021228                0.565075
2                     0.214348              0.010068                0.553522
3                     0.209648              0.005857                5.299407
4                     0.201268              0.019254               -2.655558
5                     0.180277              0.008406               -2.243170
6                     0.121976              0.012358                0.741234
7                     0.113862              0.002437               -0.459225
8                     0.094065              0.007480               -2.203349
9                     0.073183              0.002110                0.401326
10                    0.069058              0.000474               -0.565729
11                    0.059394              0.001699               -2.841782
12                    0.053492              0.000076                0.572350
13                    0.051462              0.011117               -4.751399
14                    0.044621              0.001428                1.726456
15                    0.038060              0.002472                2.900067
16                    0.035086              0.000642                2.847032
17                    0.027002              0.012311               -3.224638
18                    0.023652              0.003301               -0.401571
19                    0.017891              0.013588               -2.357813
20                    0.010771              0.003337                1.775200
21                    0.005131              0.003372                1.644813
第三次迭代非常快,它可以在3秒内尝试10000种组合。但按照这个速度,要通过18297702361个组合需要2000多小时

def average(nump_df, x, y):
mask = (nump_df[:, 0] >= x) & (nump_df[:, 1] >= y)
filterArr = nump_df[mask]
if filterArr.size == 0:
    return None, None

return filterArr[:,2].mean(), filterArr.shape[0]

def process_all(df):
df.dropna(inplace=True)
nump_df = df.values
nump_df = nump_df[nump_df[:,0].argsort()[::-1]]
max_avg = 0
final_list = []
i = 0
# rows: 135,269
# combinations: 18,297,702,361
for x,y in itertools.product(nump_df[:,0],nump_df[:,1]):
    avg, count = average(nump_df, x, y)
    if avg is None:
        continue

    if avg > max_avg:
        max_avg = avg
        max_row = [x, y, avg, count]
        final_list.append(max_row)
    if (i % 10000) == 0:
        print(i)
    i = i + 1 

final_array = np.array(final_list)
return final_array 
编辑4:

        0  1  2
0                     0.955264              0.018151                1.069599
1                     0.250984              0.021228                0.565075
2                     0.214348              0.010068                0.553522
3                     0.209648              0.005857                5.299407
4                     0.201268              0.019254               -2.655558
5                     0.180277              0.008406               -2.243170
6                     0.121976              0.012358                0.741234
7                     0.113862              0.002437               -0.459225
8                     0.094065              0.007480               -2.203349
9                     0.073183              0.002110                0.401326
10                    0.069058              0.000474               -0.565729
11                    0.059394              0.001699               -2.841782
12                    0.053492              0.000076                0.572350
13                    0.051462              0.011117               -4.751399
14                    0.044621              0.001428                1.726456
15                    0.038060              0.002472                2.900067
16                    0.035086              0.000642                2.847032
17                    0.027002              0.012311               -3.224638
18                    0.023652              0.003301               -0.401571
19                    0.017891              0.013588               -2.357813
20                    0.010771              0.003337                1.775200
21                    0.005131              0.003372                1.644813
这是行不通的。整个数据集需要136 GB的内存。在一个小数据集上,它不能返回正确的Z值。不过速度很快

class Optimizer(object):
nump_df: np.array

def __init__(self):
    self.nump_df = None

@np.vectorize
def average(self, x, y):
    mask = (self.nump_df[:, 0] >= x) & (self.nump_df[:, 1] >= y)
    filterArr = self.nump_df[mask]
    if filterArr.size == 0:
        return None

    return filterArr[:,2].mean() #, filterArr.shape[0]

def process_all(self, df):
    df.dropna(inplace=True)
    self.nump_df = df.values
    xx, yy = np.meshgrid(self.nump_df[:,0], self.nump_df[:,1], sparse=True, indexing='xy')
    X = xx.T
    Y = yy.T
    Z = self.average(self,X,Y)
    print(Z)
编辑5:

        0  1  2
0                     0.955264              0.018151                1.069599
1                     0.250984              0.021228                0.565075
2                     0.214348              0.010068                0.553522
3                     0.209648              0.005857                5.299407
4                     0.201268              0.019254               -2.655558
5                     0.180277              0.008406               -2.243170
6                     0.121976              0.012358                0.741234
7                     0.113862              0.002437               -0.459225
8                     0.094065              0.007480               -2.203349
9                     0.073183              0.002110                0.401326
10                    0.069058              0.000474               -0.565729
11                    0.059394              0.001699               -2.841782
12                    0.053492              0.000076                0.572350
13                    0.051462              0.011117               -4.751399
14                    0.044621              0.001428                1.726456
15                    0.038060              0.002472                2.900067
16                    0.035086              0.000642                2.847032
17                    0.027002              0.012311               -3.224638
18                    0.023652              0.003301               -0.401571
19                    0.017891              0.013588               -2.357813
20                    0.010771              0.003337                1.775200
21                    0.005131              0.003372                1.644813
整个数据集是什么样子的?
我能够实现一个更快的版本。但它使用了更多内存,因为它将所有内容都列在两个大的numpy数组中(shape
[n\u unique\u x\u值,n\u unique\u y\u值]
)。如果x和y各有大约128k的唯一值,则这对于128k行是不可行的。但你也许可以进一步改进它。例如,查找每行的索引
i_x
i_y
的时间可以从
O(N)
减少到
O(logn)
甚至
O(1)
通过使用dict。两个数组
计数可以被一些稀疏的数据结构替换,尽管我不确定如何工作(一些嵌套的间隔数据结构?)


有趣的是,我的实现为您的示例输入提示了一个“更好”的解决方案,因为有x和y的多个组合提示z的相同平均值,而在我的实现中,恰好最先找到了y最小的解决方案(可能是因为它是最左上角的解决方案)而在您的实现中,会返回另一个x和y的组合。

您是正确的。我无法在真实的数据集上运行此操作。sums=np.zeros([len(xs),len(ys)])内存错误:无法分配136。GiB对于具有形状(135091、135022)和数据类型float64的数组,必须有一种应用、lambda或向量化函数的方法,以便不需要类似于此解决方案的for循环。x和y在完整数据集中是如何分布的?如果它们之间没有很强的相关性,可以尝试将数据集分割成矩形。假设可以将xy矩阵划分为4x4个矩形,每个矩形包含大约1/16行。对于其中一个矩形中的行x'y'z',它们没有很好的相关性,而是将z'添加到每个元素x中。这是一个有趣的想法。我有一个普通比赛的想法。但我不知道该怎么做。我将添加发行版的图像作为注释。