2017-10-16 122 views
0

我已經找到了所有的值和所有的東西,我嘗試了排序,但它是分開排序而不是一起排序的。我想按年分類,分數應該遵循年的價值。然而,當我做分類(年)時,它只會分類幾年,留下成績。對來自兩個不同陣列的數值進行排序

打開文件時, 它會給我是這樣的:

Year,Grade 
2000,84 
2001,34 
2002,82 
2012,74 
2008,90 

等等。所以我計算了平均值和一切。

years, average_grades = [],[] 
avg = [] 
d = {} 

with open(file,'r') as f: 
    next(f) 
    for line in f: 
     year, grade = (s.strip() for s in line.split(',')) 
     if year in d: 
      d[year][0] += int(grade) 
      d[year][1] += 1 
     else: 
      d[year] = [int(grade),1] 

    for year, grades in d.items(): 
     years.append(str(year)) 
     average_grades.append(float(grades[0])/grades[1]) 

    return years, average_grades 

沒有排序,它會給我與此類似:

2001 74.625 
2006 72.241 
2012 70.875 
2017 69.1981 
2005 72.5 
2008 71.244 
2014 73.318 
2004 72.1 
2007 72.88 
2000 73.1 

With years.sort(), it would give me similar to this: 
2000 74.625 
2001 72.241 
2002 70.875 
2003 69.1981 
2004 72.5 
2005 71.244 
2006 73.318 
2007 72.1 

所以那種只會工作多年,但不會做的成績。 這個問題一直困擾着我很長一段時間。我不打算使用熊貓。

+0

您可以發佈數據 –

+0

我所提供的示例數據的例子。 – Mayjunejuly

+0

問題是你正在返回兩個_independent_數據結構。返回的'years'和'average_grades'在您返回時無關。 – Unapiedra

回答

0

你想return語句前加上這一行:

years, average_grades = zip(*sorted(zip(years, average_grades), key=lambda p: p[0])) 

這是什麼呢?

內部zip(years, average_grades)告訴python將迭代器yearsaverage_grades的每個元素作爲元組數組放在一起。

sorted(..., key=lambda p: p[0])sorted實用程序,除了現在它在對上運行,它需要知道如何對這對進行排序。所以我們給它傳遞一個lambda函數,說「看第一部分」。

zip(*...)從排序的,這是一個元組列表返回結果,並將其轉換回兩個列表。 *告訴它將這個列表視爲一大堆參數,所以你成對傳遞給zip。 zip接受任意數量的元組參數,並將它們拆分爲其組成部分。在這種情況下,它取十對並將它分成兩個長度爲10的元組。

只要你的迭代器具有相同的長度,這是將它們排序在一起的「基本」機制。

+0

不是一個好的答案:如果OP可以控制發佈的代碼,那麼將'(年,年級)'元組保存在一起會更清晰。然後排序,然後解壓縮。雖然沒有失望。 – Unapiedra

+0

分別維護變量和壓縮它們之間唯一的區別是使用zip。有很多真實世界的例子,你會有兩組獨立的數據。 @Unapiedra,請記住Stack Overflow的目標是爲將來的用戶創建一個知識庫。斷言在這種情況下,不分離兩個列表將是更好的解決方案;由於您爲此特定實例提供的實施,聲稱提供足夠信息以幫助未來提問者的答案「不是一個好答案」是無效的。 –

1

使用zip加入他們作爲tuple,然後sort

>>> y = [3, 2, 4, 1, 2] 
>>> g = [0.1, 0.4, 0.2, 0.7, 0.1] 

>>> mix = list(zip(y,g)) 
>>> mix 
=> [(3, 0.1), (2, 0.4), (4, 0.2), (1, 0.7), (2, 0.1)] 

>>> sorted(mix) 
=> [(1, 0.7), (2, 0.1), (2, 0.4), (3, 0.1), (4, 0.2)] 

#PRINT在您的訂單:

>>> for ele in sorted(mix): 
     print(ele[0],ele[1]) 

1 0.7 
2 0.1 
2 0.4 
3 0.1 
4 0.2 

注意表示,今年2,還有0.10.4兩個值,它處理它給予更多的優先year和接下來grades

0

我希望這個例子將是有幫助的,所以:

years = [2001,2000,2002] 
average_grades = [5,10,15] 
result = zip(years,average_grades) 
for item in sorted(result, key=lambda x: x[0]): 
    print('{} {}'.format(*item)) 
#2000 10 
#2001 5 
#2002 15 
0

的替代解決方案正在服用的結果,並荏苒在一起。由於您似乎對文件的閱讀有控制權,我建議改爲永不拆分年份和成績

在我看來,這比稍後將兩個列表與zip結合起來更容易。

years, average_grades = [],[] 
avg = [] 
d = {} 

with open(file,'r') as f: 
    next(f) 
    for line in f: 
     year, grade = (s.strip() for s in line.split(',')) 
     if year in d: 
      d[year][0] += int(grade) 
      d[year][1] += 1 
     else: 
      d[year] = [int(grade),1] 

# Iterator-Expression to convert 'd' dictionary into list of tuples. 
# Puts (year, average grade) into a new list. 
year_grade = [(year, float(grade_tuple[0])/grade_tuple[1]) \ 
       for year, grade_tuple in d.items()] 

# Sorting is optional, if you return the list of tuples. 
# Use 'key=lambda ...' to sort over the year (the first element of the tuple). 
# Technically, specyfing the 'key' is not necessary as the default would be 
# to sort over the first element first. 
year_grade.sort(key=lambda x: x[0]) 

return year_grade 
# Alternatively, return the list of tuples as a list of two tuples: years, grades 
return zip(*year_grade) 

其他改進

可以使用defaultdict避免if year in d塊:

from collections import defaultdict 

d = defaultdict(lambda: [0, 0]) 

with open(fname,'r') as f: 
    next(f) 
    for line in f: 
     year, grade = (s.strip() for s in line.split(',')) 
     d[year][0] += int(grade) 
     d[year][1] += 1 

    def avg(t): 
     return float(t[0])/t[1] 
    year_grade = [(y, avg(g)) for y, g in d.items()] 
    year_grade.sort() 

    return zip(*year_grade) # Python3: tuple(zip(*year_grade)) 
相關問題