2017-03-24 65 views
0

我有兩個分別來自2016和2017的數據字典,它們具有相同的5個鍵。我想計算每個鍵的值與其字典中的值之和的百分比,然後將每個單獨鍵的兩個百分比加入標籤。我已經設法做到了這一點,但我的方法需要很多循環,似乎有點笨重。我正在尋找凝聚或重寫我的代碼的方法,以使其更有效率。Python - 合併循環

UsersPerCountry, UsersPerPlatform, UsersPerPlatform2016, UsersPerPlatform2017 = Analytics.UsersPerCountryOrPlatform() 

labels = [] 
sizes16 = [] 
sizes17 = [] 
sumc1 = 0 
sumc2 = 0 
percentages = [] 

for k, v in dict1.iteritems(): 
    sumv1 += v 
for k, v in dict1.iteritems(): 
    v1 = round(((float(v)/sumc1) * 100), 1) 
    percentages.append(v1) 
    labels.append(k) 
    sizes16.append(c) 
for k, v in dict2.iteritems(): 
    sumv1 += v 
for k, v in dict2.iteritems(): 
    v2 = round(((float(v)/sumc1) * 100), 1) 
    percentages.append(v2) 
    sizes17.append(c) 
for i in range(5): 
    labels[i] += (', ' + str(percentages[i]) + '%' + ', ' + str(percentages[i + 5]) + '%') 

這是標籤的樣子:

enter image description here

編輯:我現在已經增加了變量聲明。我認爲將所有變量設置爲空列表或0的散列行就足夠了。

+1

請張貼一個完整的代碼片段。例如'sumc1'和'c'永遠不會被宣佈...... – brianpck

+1

你有沒有考慮過使用'Pandas'?您可以將每個字典放入一個'pd.DataFrame'中,並使用熊貓的向量化機制來執行兩行相同的計算。即'df = pd.DataFrame(dict1)'和'df2 = pd.DataFrame(dict2)',或者甚至將它們組合成單個'df = pd.concat([df1,df2],keys = [2016,2017] )'。 –

回答

1

您可以使用熊貓的數據框架類來簡化事情。我有點不確定你的百分比是如何被計算的,這樣可能需要摸索出了一點,但否則,試試這個:

import pandas as pd 

#convert data to DataFrame class 
df1 = pd.DataFrame(dict1) 
df2 = pd.DataFrame(dict2) 

#compute the percentages 
percnt1 = df1.sum(axis=0).div(df1.sum().sum()) 
percnt2 = df2.sum(axis=0).div(df2.sum().sum()) 

#to get the sum: 
percnt1 + percnt2 

下面是一個例子:

## create a data frame: 
import numpy as np 
df1 = pd.DataFrame({'Android':np.random.poisson(10,100), 'iPhone':np.random.poisson(10,100), 
'OSX':np.random.poisson(10,100), 'WEBGL':np.random.poisson(10,100), 'Windows':np.random.poisson(10,100)}) 

In [11]: df1.head() 
Out[11]: 
    Android OSX WEBGL Windows iPhone 
0  12 12  9  9  5 
1  9 8  14  7  11 
2  12 10  7  10  11 
3  11 12  7  17  5 
4  15 16  15  11  13 

In [10]: df1.sum(axis=0).div(df1.sum(axis=0).sum()) 
Out[10]: 
Android 0.205279 
OSX  0.198782 
WEBGL  0.200609 
Windows 0.198376 
iPhone  0.196954 
dtype: float64 
1

沒有大熊貓:

您應該利用一些Python的內置功能以及函數。在這裏,我試圖複製你正在做的更多Pythonic。

注意這是未經測試的,因爲您沒有給出完整的代碼片段(sumc1和c未聲明)。我基於我認爲你想要做的事情寫了這篇文章。

# Your size16/size17 lists appear to be full of the constant c 
# can use Pythons list replication operation 
sizes16 = [c]*len(dict1) 
sizes17 = [c]*len(dict2) 

# define function for clarity/reduce redundancy 
def get_percentages(l): 
    s = sum(l) 
    percentages = [ round(((float(n)/s)*100),1) for n in l ] # percentages calculation is a great place for list comprehension 
    return percentages 

# can grab the labels directly, rather than in a loop 
labels = dict1.keys() 

percentages1 = get_percentages(dict1.values()) 
percentages2 = get_percentages(dict2.values()) 

# no magic number 5 
for i in range(len(labels)): 
    labels[i] += (', ' + str(percentages[i]) + '%' + ', ' + str(percentages[i + 5]) + '%') 

如果我對自己在做什麼有了更好的瞭解,那麼可以清理最後一行。

我沒仔細看過,但是這段代碼可能會在數據上運行一次或兩次,因此效率可能會稍差。但是,它更可讀的IMO。

1

這是一種無需外部庫的方法。你沒有提到代碼運行方式中的任何問題,只是它是美學的(哪一個人可能會認爲它會影響它的運行方式)。無論如何,這看起來乾淨:

# Sample data 
d1 = {'a':1.,'b':6.,'c':10.,'d':5.} 
d2 = {'q':10.,'r':60.,'s':100.,'t':50.} 

# List comprehension for each dictionary sum 
sum1 = sum([v for k,v in d1.items()]) 
sum2 = sum([v for k,v in d2.items()]) 

# Using maps and lambda functions to get the distributions of each dictionary 
d1_dist = map(lambda x: round(x/sum1*100, 1), list(d1.values())) 
d2_dist = map(lambda y: round(y/sum2*100, 1), list(d2.values())) 


# Insert your part with the labels here (I really didn't get that part) 

>>> print(d1_dist) 
[4.5, 45.5, 27.3, 22.7] 

如果你想從字典到這些新的分配值加入原來的鑰匙,只需使用:

d1_formatted = dict(zip(list(d1.keys()), d1_dist)) 
>>> print(d1_formatted) 
{'a': 4.5, 'c': 45.5, 'b': 27.3, 'd': 22.7}