Python 使用阵列/其他方法进行优化

Python 使用阵列/其他方法进行优化,python,pandas,csv,Python,Pandas,Csv,我有这段代码,主要用于预测预测值/实际值(一个部门生产的单位),预测值是从一个文件夹中提取的,其中有100个标记为1-100的csv文件。我告诉程序返回之前的文件,并将其与实际生成的值(在basefile/baseheader中给出)进行比较。基本上,每个文件都有当前月份生成的实际单位,然后有12个月的预测。我用这个程序来计算它,但是它运行得很慢。当我指定的范围较大时,图形显示需要30秒以上的时间,但是如果我只是看到几个月的范围,它会非常快。有人告诉我,我需要更改代码中表示onetotal、tw

我有这段代码,主要用于预测预测值/实际值(一个部门生产的单位),预测值是从一个文件夹中提取的,其中有100个标记为1-100的csv文件。我告诉程序返回之前的文件,并将其与实际生成的值(在basefile/baseheader中给出)进行比较。基本上,每个文件都有当前月份生成的实际单位,然后有12个月的预测。我用这个程序来计算它,但是它运行得很慢。当我指定的范围较大时,图形显示需要30秒以上的时间,但是如果我只是看到几个月的范围,它会非常快。有人告诉我,我需要更改代码中表示onetotal、twototal、threetotal等的部分,并将它们更改为数组。但是,我不确定如何进行这项工作,我也不知道以后如何绘制精确的值(因为我需要绘制一个总数,然后绘制两个总数,等等(然后显示一个Totalist、两个Totalist的值的分布),关于如何处理这个问题以加快程序的速度,有什么想法吗

import csv
import pandas as pd
import matplotlib.pyplot as plt

# Beginning part of code is user input and calcultions to determine the Department,Range, and there is a function called getfileheader


def nmonthaccuracy(basefilenumber, n):
    basefileread = pd.read_csv(str(basefilenumber) + ".csv", encoding="Latin-1")
    baseheader = getfileheader(basefilenumber)
    basefilevalue = basefileread.loc[
        basefileread["Customer"].str.contains(Department, na=False), baseheader
    ]

    nmonthread = pd.read_csv(str(basefilenumber - n) + ".csv", encoding="Latin-1")
    nmonthvalue = nmonthread.loc[
        nmonthread["Customer"].str.contains(Department, na=False), baseheader
    ]

    return (
        (1 - (int(basefilevalue) / int(nmonthvalue)) + 1)
        if int(nmonthvalue) > int(basefilevalue)
        else int(nmonthvalue) / int(basefilevalue)
    )


N = 13
total = [0] * N
total_by_month_list = [[] for _ in range(N)]
for basefilenumber in range(int(StartRange), int(EndRange)):
    for n in range(N):
        total[n] += nmonthaccuracy(basefilenumber, n)
        total_by_month_list[n].append(nmonthaccuracy(basefilenumber, n))

onetotal=total[1]/ Range
twototal=total[2]/ Range
threetotal=total[3]/ Range
fourtotal=total[4]/ Range
fivetotal=total[5]/ Range
sixtotal=total[6]/ Range
seventotal=total[7]/ Range
eighttotal=total[8]/ Range
ninetotal=total[9]/ Range
tentotal=total[10]/ Range
eleventotal=total[11]/ Range
twelvetotal=total[12]/ Range
onetotallist=total_by_month_list[1]
twototallist=total_by_month_list[2]
threetotallist=total_by_month_list[3]
fourtotallist=total_by_month_list[4]
fivetotallist=total_by_month_list[5]
sixtotallist=total_by_month_list[6]
seventotallist=total_by_month_list[7]
eighttotallist=total_by_month_list[8]
ninetotallist=total_by_month_list[9]
tentotallist=total_by_month_list[10]
eleventotallist=total_by_month_list[11]
twelvetotallist=total_by_month_list[12]






x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
y = [
    onetotal,
    twototal,
    threetotal,
    fourtotal,
    fivetotal,
    sixtotal,
    seventotal,
    eighttotal,
    ninetotal,
    tentotal,
    eleventotal,
    twelvetotal,
]
z = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
w = [
    (onetotallist),
    (twototallist),
    (threetotallist),
    (fourtotallist),
    (fivetotallist),
    (sixtotallist),
    (seventotallist),
    (eighttotallist),
    (ninetotallist),
    (tentotallist),
    (eleventotallist),
    (twelvetotallist),
]


fig, ax = plt.subplots()
for ze, we in zip(z, w):
    plt.scatter([ze] * len(we), we, marker="D", s=5)


plt.xlabel("Number of months forecast")
plt.ylabel("Predicted/Actual ratio")
plt.title("Predicted to actual ratio for n month forecast")
ax.plot(x, y, label="Predicted/Actual")
for a, b in zip(x, y):
    plt.text(a, b, str(round(b, 2)))
plt.scatter(x, y)
plt.show()
这是一个虚拟csv文件:

和我的图表(如果好奇的话)

好的,有几件事:

  • 您读取每个文件24次(每个N读取两次)
  • 在生成x/y/z/w时存在不必要的重复
我所做的优化/更改大致如下:

  • 使用lru_缓存装饰器确保每个文件只读取一次(并保存在内存中;如果出现问题,可以限制lru缓存的大小--请参阅文档)
  • 对列表(0..11)使用基于零的索引;这是Python的惯用法
请注意,这是干编码,因此可能有一些错误或遗漏:)



您已经有了
total
total\u by\u month\u列表
。。。为什么您还需要这些额外的
…total
…totalist
变量?@AKX,因为我使用这些变量并绘制它们来生成我显示的图形,除非有另一种我不知道的方法可以这样做?您不必从列表中提取变量来将它们用于图形。介意添加您省略的Matplotlib代码吗?:)@好的,我加进去了!好的,谢谢。让我看看……哇,看起来棒极了!谢谢你的解释。让我试着在我的代码中实现它,我会让你知道它是如何运行的!:)我的图表现在立即出现!非常感谢你。这也是一次很棒的学习经历,因为我不知道代码中的functools部分。再次感谢你!嗨,我的程序的下一部分实际上要求我对变量进行等式运算,比如我设置为一个整数的变量。这段代码有没有办法仍然设置一个总值,这样我就可以进行这样的计算:一个总值调整=一个总值*1.2?您可以使用列表理解来调整整个数组:
adjusted=[value*1.2 for value in total]
。这样就没有办法单独进行了?因为我必须对每一个都有不同的方程式(一个总数可能乘以1.2,其中两个总数可能乘以1.5,依此类推)
import functools

import pandas as pd
import matplotlib.pyplot as plt

Department = ...
Range = ...
StartRange = ...
EndRange = ...


# The lru_cache decorator will ensure each file is read into memory only once (and kept there)
@functools.lru_cache()
def read_file(n):
    return pd.read_csv(str(n) + ".csv", encoding="Latin-1")


def nmonthaccuracy(basefilenumber, n):
    basefileread = read_file(basefilenumber)
    baseheader = getfileheader(basefilenumber)
    basefilevalue = basefileread.loc[
        basefileread["Customer"].str.contains(Department, na=False), baseheader
    ]

    nmonthread = read_file(basefilenumber - n)
    nmonthvalue = nmonthread.loc[
        nmonthread["Customer"].str.contains(Department, na=False), baseheader
    ]

    return (
        (1 - (int(basefilevalue) / int(nmonthvalue)) + 1)
        if int(nmonthvalue) > int(basefilevalue)
        else int(nmonthvalue) / int(basefilevalue)
    )


N = 12
total_by_month_list = [[] for _ in range(N)]
for basefilenumber in range(int(StartRange), int(EndRange)):
    for n in range(N):
        # note "n+1" below since n is now zero-indexed
        total_by_month_list[n].append(nmonthaccuracy(basefilenumber, n + 1))

total = [sum(by_month) for by_month in total_by_month_list]

x = list(range(1, N + 1))  # [1..12]
y = [t / Range for t in total]
z = x  # same as x
w = total_by_month_list

# ... matplotlib code ...