2013-06-04 7 views
6

Так что я читаю в кодах станции CSV файл из NOAA, который выглядит следующим образом:Панды read_csv DTYPE ведущих нулей

"USAF","WBAN","STATION NAME","CTRY","FIPS","STATE","CALL","LAT","LON","ELEV(.1M)","BEGIN","END" 
"006852","99999","SENT","SW","SZ","","","+46817","+010350","+14200","","" 
"007005","99999","CWOS 07005","","","","","-99999","-999999","-99999","20120127","20120127" 

Первые два столбец содержит коды для метеорологических станций, а иногда они имеют ведущие нули. Когда панды импортируют их без указания типа dtype, они превращаются в целые числа. Это не очень большая сделка, потому что я могу прокрутить индекс данных и заменить их чем-то вроде "%06d" % i, так как они всегда шесть цифр, но вы знаете ... это ленивый способ.

CSV-получают, используя этот код:

file = urllib.urlopen(r"ftp://ftp.ncdc.noaa.gov/pub/data/inventories/ISH-HISTORY.CSV") 
output = open('Station Codes.csv','wb') 
output.write(file.read()) 
output.close() 

, который все хорошо, но когда я иду и попытаться прочитать его с помощью этого:

import pandas as pd 
df = pd.io.parsers.read_csv("Station Codes.csv",dtype={'USAF': np.str, 'WBAN': np.str}) 

или

import pandas as pd 
df = pd.io.parsers.read_csv("Station Codes.csv",dtype={'USAF': str, 'WBAN': str}) 

Я получаю неприятное сообщение об ошибке:

File "C:\Python27\lib\site-packages\pandas-0.11.0-py2.7-win32.egg\pandas\io\parsers.py", line 401, in parser 
_f 
    return _read(filepath_or_buffer, kwds) 
    File "C:\Python27\lib\site-packages\pandas-0.11.0-py2.7-win32.egg\pandas\io\parsers.py", line 216, in _read 
    return parser.read() 
    File "C:\Python27\lib\site-packages\pandas-0.11.0-py2.7-win32.egg\pandas\io\parsers.py", line 633, in read 
    ret = self._engine.read(nrows) 
    File "C:\Python27\lib\site-packages\pandas-0.11.0-py2.7-win32.egg\pandas\io\parsers.py", line 957, in read 
    data = self._reader.read(nrows) 
    File "parser.pyx", line 654, in pandas._parser.TextReader.read (pandas\src\parser.c:5931) 
    File "parser.pyx", line 676, in pandas._parser.TextReader._read_low_memory (pandas\src\parser.c:6148) 
    File "parser.pyx", line 752, in pandas._parser.TextReader._read_rows (pandas\src\parser.c:6962) 
    File "parser.pyx", line 837, in pandas._parser.TextReader._convert_column_data (pandas\src\parser.c:7898) 
    File "parser.pyx", line 887, in pandas._parser.TextReader._convert_tokens (pandas\src\parser.c:8483) 
    File "parser.pyx", line 953, in pandas._parser.TextReader._convert_with_dtype (pandas\src\parser.c:9535) 
    File "parser.pyx", line 1283, in pandas._parser._to_fw_string (pandas\src\parser.c:14616) 
TypeError: data type not understood 

Это довольно большой csv (строки 31k), так что, возможно, это имеет какое-то отношение к нему?

+0

я обнаружил, что с помощью объекта работает, чтобы сохранить ведущие нули: DTYPE = {'USAF': object, 'WBAN': object} из этого сообщения: http: // stackoverflow.com/questions/13293810/import-pandas-dataframe-column-as-string-not-int –

+0

Немного странно, что str/np.str не просто работает ...: SI действительно интересно, является ли это ошибкой, может стоит опубликовать [вопрос о github] (https://github.com/pydata/pandas/issues). –

+0

Да, я думал, что это было странно, так как я мог использовать другие типы данных данных там. –

ответ

2

Похоже, вы должны указать длину строки, если вы не хотите, чтобы это был объект.
Например:

dtype={'USAF': '|S6'} 

Я не могу найти ссылку для этого, но я, кажется, припоминаю Уэса обсуждали этот самый вопрос (возможно, в разговоре). Он предположил, что numpy не допускает «правильные» строки переменной длины (см. Этот question/answer), и использование максимальной длины для заполнения массива будет чаще, чем не быть невероятно пространственным неэффективным (даже если строка короткая, она будет использоваться как много места как самая длинная строка).

Как @Wes указывает, что это также случай, когда:

dtype={'USAF': object} 

работает так же хорошо.

+2

Я бы предложил просто '{'USAF': object}' –

+1

@WesMcKinney отличная точка (как всегда)! –

5

Эта проблема вызвала у меня всевозможные головные боли при разборе файла с серийными номерами. По неизвестным причинам 00794 и 000794 представляют собой два разных серийных номера. В конце концов я придумал

converters={'serial_number': lambda x: str(x)} 
+1

Почему бы просто не написать 'converters = {'serial_number': str}'? –

+0

Возможно, потому что я не думал об этом :) –

+0

не работает для pandas == 0.20.2 –

4

Это вопрос панд DTYPE угадывание.

Pandas видит номера и догадки вы хотите, чтобы это были цифры.

Чтобы панды не сомневаться в своих намерениях, вы должны установить DTYPE вы хотите: object

pd.read_csv('filename.csv', dtype={'leading_zero_column_name': object}) 

будет делать трюк

+0

Для получения дополнительной информации метод 'read_csv' возвращает [DataFrame.] (Http://pandas.pydata.org/ pandas-docs/stable/generated/pandas.DataFrame.html # pandas.DataFrame) И значение по умолчанию для каждого поля выводится. Явным образом заявляя 'dtype', полученный DataFrame будет корректно обрабатывать поля. – Nathan

+0

не работает для pandas == 0.20.2 –

+0

@ DanielM вы уверены? Док за 0.22 утверждает, что должен. Я тестировал его в 0.11 -> 0.14, поэтому было бы странно не иметь такого поведения в версиях между ... – firelynx

Смежные вопросы