2017-04-20 75 views
2

我試圖在一整年內繪製一個城市的天氣數據,例如high_temp_f和low_temp_f,數據已經存儲在一個CSV文件中。我寫了一個函數來獲取我需要的列,以便將它們繪製在圖表中,但該函數只能在我第一次使用它時才返回數據。Python:爲什麼從CSV文件中獲取列的數據的功能只能第一次返回數據?

CSV文件結構如下:

date,high_temp_f,avg_temp_f,low_temp_f 
2016-04-18,69,58,46 
2016-04-19,59,52,46 
2016-04-20,80,63,46 

我寫的代碼如下:

import csv 

def data_to_list(data_index): 
    """ save data to a list """ 
    results = [] 
    for row in data: 
     results.append(int(row[data_index])) 
    return results 

filename = 'city.csv' 
with open(filename) as f_city: 
    data = csv.reader(f_city) 
    header = next(data) 


    high_temp_f_bj = data_to_list(1) 
    low_temp_f_bj = data_to_list(3) 

print(high_temp_f_bj) 
print(low_temp_f_bj) 

的輸出如下:

[69, 59, 80] 
[] 

我得到了high_temp_f_bj的結果是[69,59,80],但對於low_temp_f_bj,我只有[]。但是,如果刪除high_temp_f_bj = data_to_list(1)和​​的代碼,我可以得到low_temp_f_bj的正確輸出,即[46,46,46]。我感到很困惑!爲什麼我只能使用該功能?

回答

1

csv.reader返回Reader object這是一個迭代,因此具有這樣的數據你的狀態

這就是爲什麼您可以使用next(data)來讀取下一個(在這種情況下是第一行)的數據行。調用next()不僅可以提供線路,還可以提升內部狀態,因此下一個呼叫將爲您提供以下線路。這就是爲什麼您不必在data_to_list函數中再次跳過標題行的原因。

但是,這也有一個效果,即只能導航一次文件。 next()(或迭代data,它只是執行後續的next()調用)將不斷向前移動該內部行指針,直到文件結束。但是當達到目的時,你也不能再讀一遍。

一些基於文件的迭代器允許您將找到回到文件的開頭;一個CSV閱讀器不(至少據我所知)。所以,如果你想將數據進行多次處理,你將不得不解析CSV數據首次加載到內存中:

with open(filename) as f_city: 
    data = csv.reader(f_city) 
    header = next(data) 

    # create a list from the remaining contents in the iterable 
    data = list(data) 

或者,你應該考慮改變你的data_to_list功能,能夠處理多個列進行,所以你只需要通過你的文件移動一次,而不必將所有內容存儲在內存中。


如果您在理解這個迭代件事,內部指針困難,嘗試用一個更簡單的迭代器第一。您可以通過調用它iter()得到一個從任何序列:

>>> example = [1, 2, 3, 4] 
>>> iterator = iter(example) 
>>> next(iterator) 
1 
>>> next(iterator) 
2 
>>> for x in iterator: 
     print(x) 

3 
4 
>>> next(iterator) 
Traceback (most recent call last): 
    File "<pyshell#8>", line 1, in <module> 
    next(iterator) 
StopIteration 

正如你所看到的,調用next()的迭代器讓你從迭代器的下一個元素。這些調用會移動內部指針,這就是爲什麼您不會從多個next()調用中獲得相同元素的原因。當您使用for循環遍歷迭代器時,您還可以從迭代器中獲取剩餘的元素。一旦迭代器耗盡(導致for循環結束),後續調用next()將不會產生任何新結果,但會引發StopIteration異常,這是迭代器已用盡的標誌(這也是導致for循環的原因結束)。

0

一旦你讀完了這個文件,並且你到頭了,沒有什麼可讀的了。您可以重新打開它,以便每次致電data_to_list,或(更有效地)修改data_to_list以一次處理所有列。

0

發生這種情況是因爲csv.reader返回一個迭代器,並且您的data_to_list函數對其進行迭代。所以當你第二次運行函數時,迭代器就完成了。

您可以將數據加載到一個字典列表(如果它不是太大)並對其進行處理。

with open(filename) as f_city: 
    data_iterator = csv.reader(f_city) 
    header = next(data_iterator) 
    rows = list(data_iterator) 
    high_temp_data = [row['high_temp_f'] for row in rows] 
    avg_temp_data = [row['avg_temp_f'] for row in rows] 
相關問題