我的目标是用 python 创建面积图。为此,我需要一个元组列表,如下例所示。
我有这个清单:
outputs=[25,50,60,45]
我想将每个值分布在以下元组列表中:
a=(25,0,0,0)
b=(0,50,0,0)
c=(0,0,60,0)
d=(0,0,0,45)
# repeat the tupples on the following list:
data= [a,a,b,b,c,c,d,d]
pS:此数据将允许为 xx 轴上的每个类别设置面积图的 2 个上角(即 yy 轴)。
一行,双重理解匹配对角线的索引,并重复元组两次。
[tuple(x if i==j else 0 for i in range(4)) for j,x in enumerate(outputs) for _ in range(2) ]
输出:
[(25, 0, 0, 0),
(25, 0, 0, 0),
(0, 50, 0, 0),
(0, 50, 0, 0),
(0, 0, 60, 0),
(0, 0, 60, 0),
(0, 0, 0, 45),
(0, 0, 0, 45)]
但这不是最有效的,因为它构建了两次元组。
任意
outputs
长度的快速:
a = [0] * len(outputs)
data = []
for i, a[i] in enumerate(outputs):
t = *a,
data += t, t
a[i] = 0
基准测试(这并不重要,Jean-François Fabre 并没有试图让他们的速度更快,但我喜欢优化/基准测试,并且我想支持我的“快速”主张):
0.44 ± 0.00 μs Kelly_always4
1.50 ± 0.00 μs Kelly
8.33 ± 0.02 μs Jean_François_Fabre
代码(在线尝试!):
from timeit import timeit
from statistics import mean, stdev
def Kelly(outputs):
a = [0] * len(outputs)
data = []
for i, a[i] in enumerate(outputs):
t = *a,
data += t, t
a[i] = 0
return data
def Kelly_always4(outputs):
a,b,c,d=outputs
a=(a,0,0,0)
b=(0,b,0,0)
c=(0,0,c,0)
d=(0,0,0,d)
return [a,a,b,b,c,c,d,d]
def Jean_François_Fabre(outputs):
return [tuple(x if i==j else 0 for i in range(4)) for j,x in enumerate(outputs) for _ in range(2) ]
funcs = Kelly, Kelly_always4, Jean_François_Fabre
outputs = [25,50,60,45]
for f in funcs:
print(f(outputs))
times = {f: [] for f in funcs}
def stats(f):
ts = [t * 1e6 for t in sorted(times[f])[:10]]
return f'{mean(ts):6.2f} ± {stdev(ts):4.2f} μs '
for _ in range(100):
for f in funcs:
t = timeit(lambda: f(outputs), number=100) / 100
times[f].append(t)
for f in sorted(funcs, key=stats):
print(stats(f), f.__name__)
您可以使用
enumerate()
函数查找每个元素的索引并将其与元组的索引相对应:
data = []
for index, value in enumerate(outputs):
l = [0, 0, 0, 0]
l[index] = value
l = tuple(l)
data.append(l)
data.append(l)
输出:
[(25, 0, 0, 0),
(25, 0, 0, 0),
(0, 50, 0, 0),
(0, 50, 0, 0),
(0, 0, 60, 0),
(0, 0, 60, 0),
(0, 0, 0, 45),
(0, 0, 0, 45)]
此方法循环遍历所有输出值,并使用
enumerate()
函数跟踪值索引。然后,创建一个临时列表 l 并将所有值设置为 0,索引处的值除外。最后,它使用 tuple()
函数将列表转换为元组,并使用 append()
函数将其添加到数据列表中。
您可以通过提取中间有数字的填充元组的子集来构建元组:
outputs = [25,50,60,45]
data = [(0,0,0,n,0,0,0)[3-i:7-i] for i,n in enumerate(outputs) for _ in ".."]
print(*data,sep="\n")
(25, 0, 0, 0)
(25, 0, 0, 0)
(0, 50, 0, 0)
(0, 50, 0, 0)
(0, 0, 60, 0)
(0, 0, 60, 0)
(0, 0, 0, 45)
(0, 0, 0, 45)
您可以通过根据原始列表的大小设置填充来将其推广到任何大小的“输出”列表:
data = [tuple(a) for i,n in enumerate(outputs) # each item at its column pos.
for a in [[0]*len(outputs)] # padding = length
for a[i] in [n,n] ] # assigned twice