2017-05-03 2 views
1

팬드 데이터 프레임에 this wind file (wind.txt ~1MB)을 구문 분석하는 함수를 작성했지만 파일 형식의 불명예로 인해 제 동료에 따르면 속도가 매우 느립니다.판다 데이터 프레임에 대한 고정 너비의 대체 파일의 느린 구문 분석

2000 1 1 CCB Wdir 5 11 15 14 14 14 14 16 15 15 15 15 13 12 16 16 15 15 15 15 15 14 14 14 
2000 1 1 CCB Wspd 10 8 6 8 7 7 8 8 6 8 9 7 16 16 7 10 12 14 15 17 18 22 22 20 
2000 1 2 CCB Wdir 14 14 14 14 14 16 16 16 16 15 15 16 17 17 16 17 16 16 16 15 15 15 15 16 
2000 1 2 CCB Wspd 17 16 15 17 15 15 16 14 14 15 17 16 15 13 14 15 15 21 20 20 18 25 23 21 
2000 1 3 CCB Wdir 15 15 15 16 15 16 16 16 16 16 16 20 18 22 28 27 26 31 32 32 33 33 35 33 
2000 1 3 CCB Wspd 20 22 22 18 20 21 21 22 18 16 14 13 15 6 3 7 8 8 13 13 15 10 6 7 

열이 년, 월, 일, 사이트 이름, 변수 다음은 파일의 조각이야 2016 년 1900에서 위에 링크 된 파일은 시간당 바람 데이터가 큰 파일의 하위 집합입니다 이름, 시간 00, 시간 01, 시간 02, ..., 시간 23 풍향 및 풍속이 매일 매일 번갈아 나타나고 하루 24 시간의 측정이 모두 같은 선상에 있습니다.

내가하고있는 일은이 파일의 내용을 datetime 인덱스 (시간별 빈도)와 두 개의 열 (wdir 및 wspd)이있는 단일 판다 데이터 프레임으로 읽는 것입니다. 내 파서는 다음과 같습니다 :

import pandas as pd 
from datetime import timedelta 

fil = 'D:\\wind.txt' 
lines = open(fil, 'r').readlines() 
nl = len(lines) 

wdir = lines[0:nl:2] 
wspd = lines[1:nl:2] 

first = wdir[0].split() 
start = pd.datetime(int(first[0]), int(first[1]), int(first[2]), 0) 
last = wdir[-1].split() 
end = pd.datetime(int(last[0]), int(last[1]), int(last[2]), 23) 
drange = pd.date_range(start, end, freq='H') 

wind = pd.DataFrame(pd.np.nan, index=drange, columns=['wdir','wspd']) 

idate = start 

for d in range(nl/2): 
    dirStr = wdir[d].split() 
    spdStr = wspd[d].split() 
    for h in range(24): 
     if dirStr[h+5] != '-9' and spdStr[h+5] != '-9': 
      wind.wdir[idate] = int(dirStr[h+5]) * 10 
      wind.wspd[idate] = int(spdStr[h+5]) 
     idate += timedelta(hours=1) 
     if idate.month == 1 and idate.day == 1 and idate.hour == 1: 
      print idate 

지금은 내가 꽤 좋은 생각 한 해를 구문 분석하는 데 약 2.5 초 정도 걸립니다,하지만 내 동료가 그것의 전체 데이터 파일을 구문 분석 할 수 있어야한다는 생각 몇 초. 그가 맞습니까? 나는 천천히, clunky 파서를 쓰는 소중한 시간을 낭비하고 있습니까?

대규모의 레거시 FORTRAN77 모델에서 작업하고 다양한 입력/출력 파일에 대해 비슷한 수의 파서를 여러 개 만들어 파이썬에서 분석/작성/수정할 수 있습니다. 내가 그들 각자에게 시간을 절약 할 수 있다면 나는 어떻게 알고 싶다. 많은 감사합니다!

+0

코드가 이미 작동 중이면 CodeReview에서이 코드를 더 잘 게시 할 수 있습니다. 코드의 문제가 SO입니다. – asongtoruin

답변

2

나는 pd.read_fwf(...) 또는 pd.read_csv(..., delim_whitespace=True) 방법을 사용하는 것 -이 같은 파일을 구문 분석하도록 설계 ...

데모 :

cols = ['year', 'month', 'day', 'site', 'var'] + ['{:02d}'.format(i) for i in range(24)] 

fn = r'C:\Temp\.data\43763897.txt' 

df = pd.read_csv(fn, names=cols, delim_whitespace=True, na_values=['-9']) 
x = pd.melt(df, 
      id_vars=['year','month','day','site','var'], 
      value_vars=df.columns[5:].tolist(), 
      var_name='hour') 
x['date'] = pd.to_datetime(x[['year','month','day','hour']], errors='coerce') 
x = (x.drop(['year','month','day','hour'], 1) 
     .pivot_table(index=['date','site'], columns='var', values='value') 
     .reset_index()) 

결과 : 당신의 wind.txt 파일을

In [12]: x 
Out[12]: 
var     date site Wdir Wspd 
0  2000-01-01 00:00:00 CCB 5.0 10.0 
1  2000-01-01 01:00:00 CCB 11.0 8.0 
2  2000-01-01 02:00:00 CCB 15.0 6.0 
3  2000-01-01 03:00:00 CCB 14.0 8.0 
4  2000-01-01 04:00:00 CCB 14.0 7.0 
5  2000-01-01 05:00:00 CCB 14.0 7.0 
6  2000-01-01 06:00:00 CCB 14.0 8.0 
7  2000-01-01 07:00:00 CCB 16.0 8.0 
8  2000-01-01 08:00:00 CCB 15.0 6.0 
9  2000-01-01 09:00:00 CCB 15.0 8.0 
...     ... ... ... ... 
149030 2016-12-31 14:00:00 CCB 0.0 0.0 
149031 2016-12-31 15:00:00 CCB 1.0 5.0 
149032 2016-12-31 16:00:00 CCB 33.0 8.0 
149033 2016-12-31 17:00:00 CCB 34.0 9.0 
149034 2016-12-31 18:00:00 CCB 35.0 7.0 
149035 2016-12-31 19:00:00 CCB 0.0 0.0 
149036 2016-12-31 20:00:00 CCB 12.0 8.0 
149037 2016-12-31 21:00:00 CCB 13.0 7.0 
149038 2016-12-31 22:00:00 CCB 15.0 7.0 
149039 2016-12-31 23:00:00 CCB 17.0 7.0 

[149040 rows x 4 columns] 

타이밍 :

In [10]: %%timeit 
    ...: cols = ['year', 'month', 'day', 'site', 'var'] + ['{:02d}'.format(i) for i in range(24)] 
    ...: fn = r'D:\download\wind.txt' 
    ...: df = pd.read_csv(fn, names=cols, delim_whitespace=True, na_values=['-9']) 
    ...: x = pd.melt(df, 
    ...:    id_vars=['year','month','day','site','var'], 
    ...:    value_vars=df.columns[5:].tolist(), 
    ...:    var_name='hour') 
    ...: x['date'] = pd.to_datetime(x[['year','month','day','hour']], errors='coerce') 
    ...: x = (x.drop(['year','month','day','hour'], 1) 
    ...:  .pivot_table(index=['date','site'], columns='var', values='value') 
    ...:  .reset_index()) 
    ...: 
1 loop, best of 3: 812 ms per loop 
+0

이 응용 프로그램 및 다른 응용 프로그램에 pd.read_fwf()를 사용하려고했습니다. 내가 직면 한 문제는 (1) 교차하는 방향/속도 행이 실제로 해결하기 어렵다. (2) 각 시간 측정 열을 고유 한 색인 행으로 파열하는 것이 어렵고 (3) 실제 시간 필드를 자동으로 파싱하는 것은 거의 불가능합니다. pd.read_fwf()를이 입력 파일로 작업하게하는 것은 가능하지만, 위에서 설명한 프로세스보다 훨씬 느리고 훨씬 복잡합니다. 내가 틀린 일을하지 않는 한, 확실히 가능성이 있습니다. – Taylor

+1

@Taylor, 결과 DF에'site name' 열이 필요합니까? – MaxU

+2

MaxU의 코드와 wind.txt를 사용하면 298080 행에 대해 3.5 초가됩니다. 오류 = '강제 변환'을 pd.to_datetime에 추가해야했습니다. –

관련 문제