Pandas чтение csv как тип строки
У меня есть фрейм данных с буквенно-цифровыми клавишами, которые я хочу сохранить как csv и прочитать позже. По разным причинам мне нужно явно прочитать этот ключевой столбец как строковый формат, у меня есть ключи, которые являются строго цифровыми или даже хуже, такими как: 1234E5, который Pandas интерпретирует как float. Это, очевидно, делает ключ совершенно бесполезным.
Проблема в том, что когда я указываю строку dtype для фрейма данных или любого столбца, я просто возвращаю мусор. У меня есть пример кода здесь:
df = pd.DataFrame(np.random.rand(2,2),
index=['1A', '1B'],
columns=['A', 'B'])
df.to_csv(savefile)
Кадр данных выглядит так:
A B
1A 0.209059 0.275554
1B 0.742666 0.721165
Затем я прочитал его так:
df_read = pd.read_csv(savefile, dtype=str, index_col=0)
и результат:
A B
B ( <
Это проблема с моим компьютером или что-то, что я делаю неправильно здесь, или просто ошибка?
Ответы
Ответ 1
Обновление: это было исправлено: начиная с 0.11.1 передача вами str
/np.str
будет эквивалентна использованию object
.
Используйте объект dtype:
In [11]: pd.read_csv('a', dtype=object, index_col=0)
Out[11]:
A B
1A 0.35633069074776547 0.745585398803751
1B 0.20037376323337375 0.013921830784260236
или еще лучше, просто не указывайте dtype:
In [12]: pd.read_csv('a', index_col=0)
Out[12]:
A B
1A 0.356331 0.745585
1B 0.200374 0.013922
но обход обхода типа и действительно возвращение только строк требует хакерского использования converters
:
In [13]: pd.read_csv('a', converters={i: str for i in range(100)})
Out[13]:
A B
1A 0.35633069074776547 0.745585398803751
1B 0.20037376323337375 0.013921830784260236
где 100
- это число, равное или превышающее общее количество столбцов.
Лучше всего избегать str dtype, см., Например, здесь.
Ответ 2
Как сказал Антон Т в своем комментарии, pandas
будет случайным образом преобразовывать типы object
в типы с float
используя его сниффер типов, даже если вы передадите dtype=object
, dtype=str
или dtype=np.str
.
Поскольку вы можете передать словарь функций, где ключ - это индекс столбца, а значение - это функция преобразователя, вы можете сделать что-то подобное (например, для 100 столбцов).
pd.read_csv('some_file.csv', converters={i: str for i in range(0, 100)})
Вы даже можете передать range(0, N)
для N, который намного больше, чем количество столбцов, если вы не знаете, сколько столбцов вы будете читать.
Ответ 3
Используйте конвертер, который применяется к любому столбцу, если вы не знаете столбцы заранее:
import pandas as pd
class StringConverter(dict):
def __contains__(self, item):
return True
def __getitem__(self, item):
return str
def get(self, default=None):
return str
pd.read_csv(file_or_buffer, converters=StringConverter())