2011-12-17 36 views
0
Name,USAF,NCDC,Date,HrMn,I,Type,Dir,Q,I,Spd,Q 

OXNARD,723927,93110,19590101,0000,4,SAO,270,1,N,3.1,1, 
OXNARD,723927,93110,19590101,0100,4,SAO,338,1,N,1.0,1, 
OXNARD,723927,93110,19590101,0200,4,SAO,068,1,N,1.0,1, 
OXNARD,723927,93110,19590101,0300,4,SAO,068,1,N,2.1,1, 
OXNARD,723927,93110,19590101,0400,4,SAO,315,1,N,1.0,1, 
OXNARD,723927,93110,19590101,0500,4,SAO,999,1,C,0.0,1, 
.... 

OXNARD,723927,93110,19590102,0000,4,SAO,225,1,N,2.1,1, 
OXNARD,723927,93110,19590102,0100,4,SAO,248,1,N,2.1,1, 
OXNARD,723927,93110,19590102,0200,4,SAO,999,1,C,0.0,1, 
OXNARD,723927,93110,19590102,0300,4,SAO,068,1,N,2.1,1, 

這裏是在每行中的CSV文件存儲每小時風速(SPD)的一個片段。我想要做的是每天在csv文件中選擇所有小時風,並將它們存儲在臨時每日清單中,存儲當天的每小時值(如果沒有缺失值,則爲24)。然後,我將輸出當天的列表,爲第二天創建新的空列表,在第二天定位每小時的速度,輸出每日列表等等,直到文件結束。選擇內部循環某些日期爲.csv文件

我正在努力做一個好的方法來做到這一點。我想有一個想法是在第一行中讀取,確定日期(YYYY-MM-DD),然後在第i + 1行中讀取並查看該日期是否與日期i相匹配。如果他們匹配,那麼我們在同一天。如果他們不這樣做,那麼我們將在第二天進入。但我甚至不知道如何閱讀文件中的下一行...

任何建議來執行此方法或全新的(和更好的?!)方法是最受歡迎的。提前致謝!

obs_in = open(csv_file).readlines() 
for i in range(1,len(obs_in)):   
# Skip over the header lines 
if not str(obs_in[i]).startswith("Identification") and not str(obs_in[i]).startswith("Name"): 
    name,usaf,ncdc,date,hrmn,i,type,dir,q,i2,spd,q2,blank = obs_in[i].split(',') 
    current_dt = datetime.date(int(date[0:4]),int(date[4:6]),int(date[6:8])) 
    current_spd = spd 
    # Read in next line's date: is it in the same day? 
    # If in the same day, then append spd into tmp daily list 
    # If not, then start a new list for the next day 
+0

有一個列表和存儲行,直到日期更改。當日期發生變化時,將列表中的內容轉儲到文件中,刷新列表,然後轉到 – yosukesabai 2011-12-17 22:02:24

+0

,最後,是否希望有一大堆24行的文件,並且文件名變得像spd19590101.csv,spd19590102.csv等等? – yosukesabai 2011-12-17 22:20:18

+0

如何在日期更改時標記?我不知道如何閱讀下一行,並提取該日期以查看它是否與上一行的日期不同。最終,我想每個日期(YYYYMMDD)24個值的列表,輸出該列表,然後移動到第二天,有一個新的空列表,填充新的列表與下24個值,輸出它... – N1B4 2011-12-17 22:38:27

回答

0

它可以是這樣的。

def dump(buf, date): 
    """dumps buffered line into file 'spdYYYYMMDD.csv'""" 
    if len(buf) == 0: return 
    with open('spd%s.csv' % date, 'w') as f: 
     for line in buf: 
      f.write(line) 

obs_in = open(csv_file).readlines() 
# buf stores one day record 
buf = [] 
# date0 is meant for time stamp for the buffer 
date0 = None 
for i in range(1,len(obs_in)):   
    # Skip over the header lines 
    if not str(obs_in[i]).startswith("Identification") and \ 
     not str(obs_in[i]).startswith("Name"): 
     name,usaf,ncdc,date,hrmn,ii,type,dir,q,i2,spd,q2,blank = \ 
      obs_in[i].split(',') 
     current_dt = datetime.date(int(date[0:4]),int(date[4:6]),int(date[6:8])) 
     current_spd = spd 
     # see if the time stamp of current record is different. if it is different 
     # dump the buffer, and also set the time stamp of buffer 
     if date != date0: 
      dump(buf, date0) 
      buf = [] 
      date0 = date 
     # you change this. i am simply writing entire line 
     buf.append(obs_in[i]) 

# when you get out the buffer should be filled with the last day's record. 
# so flush that too. 
dump(buf, date0) 

我還發現,我必須使用ii,而不是i的數據歸檔「我」,你for循環計數器使用i

1

您可以利用數據文件的有序性,並使用csv.dictreader。然後,您可以非常簡單地構建一個按日期組織的風速字典,您可以根據需要進行處理。請注意,csv閱讀器會返回字符串,因此在組裝列表時可能需要根據需要將其轉換爲其他類型。

import csv 
from collections import defaultdict 
bydate = defaultdict(list) 
rdr = csv.DictReader(open('winds.csv','rt')) 
for k in rdr: 
    bydate[k['Date']].append(float(k['Spd'])) 

print(bydate) 
defaultdict(<type 'list'>, {'19590101': [3.1000000000000001, 1.0, 1.0, 2.1000000000000001, 1.0, 0.0], '19590102': [2.1000000000000001, 2.1000000000000001, 0.0, 2.1000000000000001]}) 

可以很明顯的改變參數的append調用一個元組,例如append((float(k['Spd']), datetime.datetime.strptime(k['Date']+k['HrMn'],'%Y%m%D%H%M))這樣你還可以收集的時間。

如果文件有多餘的空格,可以使用skipinitialspace參數:rdr = csv.DictReader(open('winds.csv','rt'), fieldnames=ff, skipinitialspace=True)。如果這仍然不起作用,你可以預先處理標題行:

bydate = defaultdict(list) 
with open('winds.csv', 'rt') as f: 
    fieldnames = [k.strip() for k in f.readline().split(', ')] 
    rdr = csv.DictReader(f, fieldnames=fieldnames, skipinitialspace=True) 
    for k in rdr: 
     bydate[k['Date']].append(k['Spd']) 
return bydate 

bydate就像一個普通的字典訪問。要訪問特定日期的數據,請執行bydate['19590101']。要獲取已處理日期的列表,您可以執行bydate.keys()

如果要在讀取文件時將它們轉換爲Python日期時間對象,可以導入datetime,然後用bydate[datetime.datetime.strptime(k['Date'], '%Y%m%d')].append(k['Spd'])替換賦值行。

+0

感謝您的建議,mtrw!後續問題:我在實際的csv文件中有一些尾隨和前導空白(我在粘貼上面的代碼片段時手動刪除了它們),因此爲了使上述腳本起作用,第6行需要是:bydate [k [ 'Date']]。append(k ['Spd'])。如何刪除讀入中的空格,以便我可以在第6行中使用'Date'和'Spd'? – N1B4 2011-12-18 03:40:38

+0

另外,你如何提取速度爲19590101,例如? (我是DictReader的總新手) – N1B4 2011-12-18 03:46:15

+0

Skipinitialspace = True似乎只刪除前導空格 - 是否有相應的命令來刪除尾隨和前導空格? – N1B4 2011-12-18 09:35:22

0

我知道這個問題是從幾年前,但只是想指出,一個小bash腳本可以整齊地執行此任務。我複製你的例子到一個文件名爲data.txt中,這是腳本:

#!/bin/bash 
date=19590101 
date_end=19590102 
while [[ $date -le $date_end ]] ; do 
    grep ",${date}," data.txt > file_${date}.txt 
    date=`date +%Y%m%d -d ${date}+1day` # NOTE: MAC-OSX date differs 
done 

請注意,這不會對MAC作爲某種原因date命令執行不同的工作。如果文件中缺少日期,則grep命令會生成一個空文件 - 此鏈接顯示避免此問題的方法: how to stop grep creating empty file if no results

相關問題