Чтение файлов CSV в numpy, где разделитель "," - PullRequest
9 голосов
/ 19 апреля 2010

У меня есть файл CSV с форматом, который выглядит следующим образом:

"FieldName1", "FieldName2", "FieldName3", "FieldName4"
«13.04.2010 14: 45: 07.008», «7.59484916392», «10», «6.552373»
«13.04.2010 14: 45: 22.010», «6.55478493312», «9», «3.5378543»
...

Обратите внимание, что в начале и конце каждой строки в файле CSV есть символы двойной кавычки, а строка "," используется для разделения полей в каждой строке. Количество полей в файле CSV может варьироваться от файла к файлу.

Когда я пытаюсь прочитать это в numpy через:
import numpy as np
data = np.genfromtxt(csvfile, dtype=None, delimiter=',', names=True)
все данные считываются как строковые значения, заключенные в двойные кавычки. Не лишено смысла, но не очень полезно для меня, так как мне нужно вернуться и преобразовать каждый столбец в правильный тип

Когда я использую delimiter='","' вместо этого, все работает, как я хотел, за исключением для 1-го и последнего полей. Поскольку символы начала и конца строки представляют собой один символ двойной кавычки, это не рассматривается как допустимый разделитель для 1-го и последнего полей, поэтому они считываются, например, как. "04/13/2010 14:45:07.008 и 6.552373" - обратите внимание на начальные и конечные символы двойной кавычки соответственно. Из-за этих избыточных символов numpy предполагает, что 1-е и последнее поля имеют оба типа String; Я не хочу, чтобы это было так

Есть ли способ указать numpy читать файлы, отформатированные таким образом, как мне хотелось бы, без необходимости возвращаться и "исправлять" структуру массива numpy после первоначального чтения?

1 Ответ

12 голосов
/ 19 апреля 2010

Основная проблема заключается в том, что NumPy не понимает концепцию удаления кавычек (в то время как модуль csv понимает).Когда вы говорите delimiter='","', вы говорите NumPy, что разделитель столбцов - это буквально кавычка, то есть кавычки вокруг запятой, а не значение, поэтому ожидаются дополнительные кавычки, которые вы получаете в первом и последнем столбцах.

Глядя на документацию по функциям, я думаю, вам нужно установить параметр converters, чтобы лишить вас кавычек (по умолчанию это не так):

import re
import numpy as np

fieldFilter = re.compile(r'^"?([^"]*)"?$')
def filterTheField(s):
    m = fieldFilter.match(s.strip())
    if m:
        return float(m.group(1))
    else:
        return 0.0 # or whatever default

#...

# Yes, sorry, you have to know the number of columns, since the NumPy docs
# don't say you can specify a default converter for all columns.
convs = dict((col, filterTheField) for col in range(numColumns))
data = np.genfromtxt(csvfile, dtype=None, delimiter=',', names=True, 
    converters=convs)

Или отказаться от np.genfromtxt()и пусть csv.csvreader дает вам содержимое файла по очереди, в виде списков строк, затем вы просто перебираете элементы и строите матрицу:

reader = csv.csvreader(csvfile)
result = np.array([[float(col) for col in row] for row in reader])
# BTW, column headings are in reader.fieldnames at this point.

РЕДАКТИРОВАТЬ: Хорошо, так что это выглядит такВаш файл не все плавает.В этом случае вы можете установить convs, как необходимо в случае genfromtxt, или создать вектор функций преобразования в случае csv.csvreader:

reader = csv.csvreader(csvfile)
converters = [datetime, float, int, float]
result = np.array([[conv(col) for col, conv in zip(row, converters)] 
    for row in reader])
# BTW, column headings are in reader.fieldnames at this point.

РЕДАКТИРОВАТЬ 2: Хорошо, переменное количество столбцов... Ваш источник данных просто хочет усложнить жизнь.К счастью, мы можем просто использовать magic ...

reader = csv.csvreader(csvfile)
result = np.array([[magic(col) for col in row] for row in reader])

... где magic() - это просто имя, которое я выбрал из головы для функции.(Психея!)

В худшем случае это может быть что-то вроде:

def magic(s):
    if '/' in s:
        return datetime(s)
    elif '.' in s:
        return float(s)
    else:
        return int(s)

Может быть, в NumPy есть функция, которая принимает строку и возвращает один элемент с правильным типом.numpy.fromstring() выглядит близко, но это может интерпретировать пространство в ваших временных метках как разделитель столбцов.

PS Один недостаток с csvreader Я вижу, что он не отбрасывает комментарии;Реальные csv файлы не имеют комментариев.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...