我有一个程序可以对大量实验数据进行操作。数据被存储为与以下属性的类的实例的对象的列表:Python:提高累计总和
- time_point - 节点的集群从该样品的名称 - 样品
- 簇的时间采取
- 节点 - 从该取样
- 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])
这将产生正确的输出,但我不知道它是否可以变得更可读/ Python化,和/或更快/更可扩展性。
上面是有吸引力的,它只能通过(大)数据集循环一次,但没有吸引力,因为我基本上复制/粘贴了相同算法的三个副本。
为了避免上述的复制/粘贴问题,我想这也:
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.
有没有人在这里堆栈溢出有改进建议?上面的第一个片段对于我的初始数据集(大约一百万条记录)运行良好,但后面的数据集将有更多的记录和群集/节点,因此可伸缩性是一个问题。
这是我对Python的第一次非平凡使用,我想确保我正在适当地利用该语言(这取代了一组非常复杂的SQL查询,而Python版本的早期版本是基本上非常无效的直接转换)。我通常不会做很多编程,所以我可能会错过一些基本的东西。
非常感谢!
您可以先执行所有节点计算,然后使用节点结果计算群集结果,然后使用群集结果计算系统范围的结果。这至少会减少你目前正在做的一些重复(相同的增加)。 – unutbu 2010-05-30 03:37:33
感谢您的建议。然而,集群峰值可能与任何单个节点的峰值不同。例如,它们可能都会立即达到中等价值,从而为集群带来巨大的高峰,但对于任何单个节点而言都不是一个巨大的高峰。 – bbayles 2010-05-30 04:30:45