gpt4 book ai didi

Python:改进长累积总和

转载 作者:行者123 更新时间:2023-12-04 06:52:25 24 4
gpt4 key购买 nike

我有一个对大量实验数据进行操作的程序。数据存储为对象列表,这些对象是具有以下属性的类的实例:

  • time_point - 样本的时间
  • cluster - 从中​​获取样本的节点集群的名称
  • node - 从中​​获取样本的节点的名称
  • qty1 = 第一个数量的样本值
  • qty2 = 第二个数量的样本值

  • 我需要从数据集中导出一些值,以三种方式分组 - 一次用于整个样本,一次用于每个节点集群,一次用于每个节点。我需要推导出的值取决于 qty1 和 qty2 的(时间排序的)累积总和:qty1 和 qty2 的累积总和的元素总和的最大值,出现最大值的时间点,以及那个时间点的 qty1 和 qty2 的值​​。

    我想出了以下解决方案:
    dataset.sort(key=operator.attrgetter('time_point'))

    # For the whole set
    sys_qty1 = 0
    sys_qty2 = 0
    sys_combo = 0
    sys_max = 0

    # For the cluster grouping
    cluster_qty1 = defaultdict(int)
    cluster_qty2 = defaultdict(int)
    cluster_combo = defaultdict(int)
    cluster_max = defaultdict(int)
    cluster_peak = defaultdict(int)

    # For the node grouping
    node_qty1 = defaultdict(int)
    node_qty2 = defaultdict(int)
    node_combo = defaultdict(int)
    node_max = defaultdict(int)
    node_peak = defaultdict(int)

    for t in dataset:
    # For the whole system ######################################################
    sys_qty1 += t.qty1
    sys_qty2 += t.qty2
    sys_combo = sys_qty1 + sys_qty2
    if sys_combo > sys_max:
    sys_max = sys_combo
    # The Peak class is to record the time point and the cumulative quantities
    system_peak = Peak(time_point=t.time_point,
    qty1=sys_qty1,
    qty2=sys_qty2)
    # For the cluster grouping ##################################################
    cluster_qty1[t.cluster] += t.qty1
    cluster_qty2[t.cluster] += t.qty2
    cluster_combo[t.cluster] = cluster_qty1[t.cluster] + cluster_qty2[t.cluster]
    if cluster_combo[t.cluster] > cluster_max[t.cluster]:
    cluster_max[t.cluster] = cluster_combo[t.cluster]
    cluster_peak[t.cluster] = Peak(time_point=t.time_point,
    qty1=cluster_qty1[t.cluster],
    qty2=cluster_qty2[t.cluster])
    # For the node grouping #####################################################
    node_qty1[t.node] += t.qty1
    node_qty2[t.node] += t.qty2
    node_combo[t.node] = node_qty1[t.node] + node_qty2[t.node]
    if node_combo[t.node] > node_max[t.node]:
    node_max[t.node] = node_combo[t.node]
    node_peak[t.node] = Peak(time_point=t.time_point,
    qty1=node_qty1[t.node],
    qty2=node_qty2[t.node])

    这会产生正确的输出,但我想知道是否可以使其更具可读性/Pythonic,和/或更快/更具可扩展性。

    上面的内容很有吸引力,因为它只循环遍历(大)数据集一次,但没有吸引力,因为我基本上复制/粘贴了相同算法的三个副本。

    为了避免上述复制/粘贴问题,我也尝试过:
    def find_peaks(level, dataset):

    def grouping(object, attr_name):
    if attr_name == 'system':
    return attr_name
    else:
    return object.__dict__[attrname]

    cuml_qty1 = defaultdict(int)
    cuml_qty2 = defaultdict(int)
    cuml_combo = defaultdict(int)
    level_max = defaultdict(int)
    level_peak = defaultdict(int)

    for t in dataset:
    cuml_qty1[grouping(t, level)] += t.qty1
    cuml_qty2[grouping(t, level)] += t.qty2
    cuml_combo[grouping(t, level)] = (cuml_qty1[grouping(t, level)] +
    cuml_qty2[grouping(t, level)])
    if cuml_combo[grouping(t, level)] > level_max[grouping(t, level)]:
    level_max[grouping(t, level)] = cuml_combo[grouping(t, level)]
    level_peak[grouping(t, level)] = Peak(time_point=t.time_point,
    qty1=node_qty1[grouping(t, level)],
    qty2=node_qty2[grouping(t, level)])
    return level_peak

    system_peak = find_peaks('system', dataset)
    cluster_peak = find_peaks('cluster', dataset)
    node_peak = find_peaks('node', dataset)

    对于(非分组)系统级计算,我也想出了这个,这很漂亮:
    dataset.sort(key=operator.attrgetter('time_point'))

    def cuml_sum(seq):
    rseq = []
    t = 0
    for i in seq:
    t += i
    rseq.append(t)
    return rseq

    time_get = operator.attrgetter('time_point')
    q1_get = operator.attrgetter('qty1')
    q2_get = operator.attrgetter('qty2')

    timeline = [time_get(t) for t in dataset]
    cuml_qty1 = cuml_sum([q1_get(t) for t in dataset])
    cuml_qty2 = cuml_sum([q2_get(t) for t in dataset])
    cuml_combo = [q1 + q2 for q1, q2 in zip(cuml_qty1, cuml_qty2)]

    combo_max = max(cuml_combo)
    time_max = timeline.index(combo_max)
    q1_at_max = cuml_qty1.index(time_max)
    q2_at_max = cuml_qty2.index(time_max)

    然而,尽管这个版本对列表推导式和 zip() 的使用很酷,但它只是为了系统级计算循环了数据集三遍,我想不出一个好的方法来做集群级和节点级计算而不做一些缓慢的事情,例如:
    timeline = defaultdict(int)
    cuml_qty1 = defaultdict(int)
    #...etc.

    for c in cluster_list:
    timeline[c] = [time_get(t) for t in dataset if t.cluster == c]
    cuml_qty1[c] = [q1_get(t) for t in dataset if t.cluster == c]
    #...etc.

    Stack Overflow 上有人有改进建议吗?上面的第一个片段对于我的初始数据集(大约一百万条记录)运行良好,但后来的数据集将有更多的记录和集群/节点,因此可扩展性是一个问题。

    这是我对 Python 的第一次非平凡使用,我想确保我正确地利用了该语言(这将取代一组非常复杂的 SQL 查询,而 Python 版本的早期版本本质上是非常低效的翻译的内容)。我通常不会做太多的编程,所以我可能会遗漏一些基本的东西。

    非常感谢!

    最佳答案

    这似乎是应用一点面向对象的经典机会。我建议将派生数据设为一个类,并将累积总和计算抽象为适用于该类的内容。

    就像是:

    class DerivedData(object):
    def __init__(self):
    self.qty1 = 0.0
    self.qty2 = 0.0
    self.combo = 0.0
    self.max = 0.0
    self.peak = Peak(time_point=0.0, qty1=0.0, qty2=0.0)

    def accumulate(self, data):
    self.qty1 += data.qty1
    self.qty2 += data.qty2
    self.combo = self.qty1 + self.qty2
    if self.combo > self.max:
    self.max = self.combo
    self.peak = Peak(time_point=data.time_point,
    qty1=self.qty1,
    qty2=self.qty2)

    sys = DerivedData()
    clusters = defaultdict(DerivedData)
    nodes = defaultdict(DerivedData)

    dataset.sort(key=operator.attrgetter('time_point'))

    for t in dataset:
    sys.accumulate(t)
    clusters[t.cluster].accumulate(t)
    nodes[t.node].accumulate(t)

    该解决方案抽象了寻找峰值的逻辑,但仍然只遍历数据集一次。

    关于Python:改进长累积总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2937383/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com