我需要组合两个列表,然后计算对应于某个值的所有值。
这两个清单是:
inControl = ["False", "False", "True", "True","False", "True", "False", "True", "True", "False", "False", "False", "False", "False", "False", "True", "False", "True", "False", "False"]
rts = [379, 396, 480, 443, 365, 280, 487, 446, 350, 367, 405, 391, 484, 359, 367, 305, 359, 479, 436, 333]
我需要对与所有rts
值对应的所有False
求和,然后对True
值进行求和(它们全部按顺序排列)。
我基本上使用zip
功能将两个列表组合在一起,但我完全不知道下一步该做什么......任何帮助都会受到赞赏。
非常感谢:)
答案 0 :(得分:2)
看起来很奇怪布尔是字符串,但是......
使用zip
,然后使用sum
匹配元素。
(为Python 3中的其他部分重新创建zip
因为zip
是可迭代的)
inControl = ["False", "False", "True", "True","False", "True", "False", "True", "True", "False", "False", "False", "False", "False", "False", "True", "False", "True", "False", "False"]
rts = [379, 396, 480, 443, 365, 280, 487, 446, 350, 367, 405, 391, 484, 359, 367, 305, 359, 479, 436, 333]
z=zip(rts,inControl)
sf=sum(x[0] for x in z if x[1]=='False')
z=zip(rts,inControl)
st=sum(x[0] for x in z if x[1]=='True')
print(sf,st)
结果:
5128 2783
也许st
可以通过与sum
进行较少的字符串比较来计算:st=sum(rts)-sf
(更多的附加内容,更少的字符串比较)
变种: True&的小循环假
s=dict()
for c in ['False','True']:
z=zip(rts,inControl)
s[c]=sum(x[0] for x in z if x[1]==c)
答案 1 :(得分:2)
Jean-François的解决方案可以很好地工作并且非常易读。但它确实对数据进行了两次传递。如果列表很小,这不是什么大问题,但如果它很大,你可以通过一次通过大致将操作时间减半。
一种通用的方法是:
totals = {}
for flag, value in zip(inControl, rts):
totals[flag] = totals.setdefault(flag, 0) + value
此代码不假设inControl
仅包含False
和True
。它实际上可以有任意数量的唯一值。
一种可行的方法是使用Counter
模块中的collections
类。 Counter
是用于跟踪计数的字典。添加两个计数器是显而易见的:相同键的值相加。我们可以为每对元素创建一个Counter
实例,并将所有计数器相加。请注意,为每个元素创建Counter
可能有点过分 - 上述解决方案更有效。但出于教育目的,此解决方案看起来像:
from collections import Counter
counters = (Counter({k: v}) for k, v in zip(inControl, rts))
sum(counters, Counter())
答案 2 :(得分:0)
您可以在列表理解或生成器exrpession的True
位置或>>> [(e,0) if c=='False' else (0,e) for e, c in zip(rts, inControl)]
[(379, 0), (396, 0), (0, 480), (0, 443), (365, 0), (0, 280), (487, 0), (0, 446), (0, 350), (367, 0), (405, 0), (391, 0), (484, 0), (359, 0), (367, 0), (0, 305), (359, 0), (0, 479), (436, 0), (333, 0)]
位置生成具有单个数字的元组:
reduce
然后,您可以使用>>> reduce(lambda x, y: (x[0]+y[0], x[1]+y[1]), (((e,0) if c=='False' else (0,e) for e, c in zip(rts, inControl))))
(5128, 2783)
:
False
您实际上可以使用True
和>>> t=reduce(lambda x, y: (x[0]+y[0], x[1]+y[1]), ((e if c=='False' else 0, e if c=='True' else 0) for e, c in zip(rts, inControl)))
>>> t[False]
5128
>>> t[True]
2783
布尔值来访问元组:
map
或者,如果对您更有意义,可以使用>>> map(sum, zip(*((e,0) if c=='False' else (0,e) for e, c in zip(rts, inControl))))
[5128, 2783]
:
>>> dict(zip([False, True], map(sum, zip(*[(e,0) if c=='False' else (0,e) for e, c in zip(rts, inControl)]))))
{False: 5128, True: 2783}
或者,你可以创建一个带有和的字典:
.groupby()
如果你有熊猫,一个很好的方法就是使用sum
和>>> import pandas as pd
>>> df=pd.DataFrame({'rts':rts, 'inControl':inControl})
>>> df
inControl rts
0 False 379
1 False 396
2 True 480
3 True 443
4 False 365
5 True 280
6 False 487
7 True 446
8 True 350
9 False 367
10 False 405
11 False 391
12 False 484
13 False 359
14 False 367
15 True 305
16 False 359
17 True 479
18 False 436
19 False 333
>>> df.groupby(inControl).sum()
rts
False 5128
True 2783
:
styles.xml
答案 3 :(得分:0)
假设:
inControl = ["False", "False", "True", "True","False", "True", "False", "True", "True", "False", "False", "False", "False", "False", "False", "True", "False", "True", "False", "False"]
rts = [379, 396, 480, 443, 365, 280, 487, 446, 350, 367, 405, 391, 484, 359, 367, 305, 359, 479, 436, 333]
我假设inControl
是一个字符串列表,而不是一个布尔列表。为了我的解决方案,我将inControl
转换为布尔值列表:
inControl = [element == 'True' for element in inControl] # ==> [False, False, ...]
使用itertools.compress
计算所有True
元素的总和:
import itertools
true_sum = sum(itertools.compress(rts, inControl)) # 2783
现在,我们可以计算false_sum
:
grand_sum = sum(rts) # 7911
false_sum = grand_sum - true_sum # 5128