чтение CSV-файлов в Scipy / Numpy в Python - PullRequest
3 голосов
/ 18 мая 2010

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

def csv2array(filename, skiprows=0, delimiter='\t', raw_header=False, missing=None, with_header=True):
    """
    Parse a file name into an array. Return the array and additional header lines. By default,
    parse the header lines into dictionaries, assuming the parameters are numeric,
    using 'parse_header'.
    """
    f = open(filename, 'r')
    skipped_rows = []
    for n in range(skiprows):
        header_line = f.readline().strip()
        if raw_header:
            skipped_rows.append(header_line)
        else:
            skipped_rows.append(parse_header(header_line))
    f.close()
    if missing:
        data = genfromtxt(filename, dtype=None, names=with_header,
                          deletechars='', skiprows=skiprows, missing=missing)
    else:
    if delimiter != '\t':
        data = genfromtxt(filename, dtype=None, names=with_header, delimiter=delimiter,
                  deletechars='', skiprows=skiprows)
    else:
        data = genfromtxt(filename, dtype=None, names=with_header,
                  deletechars='', skiprows=skiprows)        
    if data.ndim == 0:
    data = array([data.item()])
    return (data, skipped_rows)

проблема в том, что genfromtxt жалуется на мои файлы, например с ошибкой:

Line #27100 (got 12 columns instead of 16)

Я не уверен, откуда эти ошибки. Есть идеи?

Вот пример файла, который вызывает проблему:

#Gene   120-1   120-3   120-4   30-1    30-3    30-4    C-1 C-2 C-5 genesymbol  genedesc
ENSMUSG00000000001  7.32    9.5 7.76    7.24    11.35   8.83    6.67    11.35   7.12    Gnai3   guanine nucleotide binding protein alpha
ENSMUSG00000000003  0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 Pbsn    probasin

Есть ли лучший способ написать универсальную функцию csv2array? спасибо.

Ответы [ 5 ]

6 голосов
/ 18 мая 2010

Проверьте модуль Python CSV: http://docs.python.org/library/csv.html

import csv
reader = csv.reader(open("myfile.csv", "rb"), 
                    delimiter='\t', quoting=csv.QUOTE_NONE)

header = []
records = []
fields = 16

if thereIsAHeader: header = reader.next()

for row, record in enumerate(reader):
    if len(record) != fields:
        print "Skipping malformed record %i, contains %i fields (%i expected)" %
            (record, len(record), fields)
    else:
        records.append(record)

# do numpy stuff.
2 голосов
/ 18 мая 2010

Могу я спросить, почему вы не используете встроенный csv reader? http://docs.python.org/library/csv.html

Я использовал это очень эффективно с numpy / scipy. Я хотел бы поделиться своим кодом, но, к сожалению, он принадлежит моему работодателю, но написать свой собственный будет очень просто.

0 голосов
/ 17 февраля 2015

Я думаю, что подход Ника Т был бы лучшим путем. Я бы сделал одно изменение. Как я бы заменил следующий код:

for row, record in enumerate(reader):
if len(record) != fields:
    print "Skipping malformed record %i, contains %i fields (%i expected)" %
        (record, len(record), fields)
else:
    records.append(record)

с

records = np.asrray([row for row in reader if len(row) = fields ])
print('Number of skipped records: %i'%(len(reader)-len(records)) #note you have to do more than len(reader) as an iterator does not have a length like a list or tuple

Понимание списка вернет пустой массив и использует преимущества предварительно скомпилированных библиотек, которые должны значительно ускорить процесс. Кроме того, я бы порекомендовал использовать print () как функцию вместо print "", поскольку первая является стандартом для python3, который, скорее всего, является будущим, и я бы использовал logging over print.

0 голосов
/ 18 мая 2010

Я успешно использовал две методологии;(1): если мне просто нужно прочитать произвольный CSV, я использовал модуль CSV (как указано другими пользователями), и (2): если мне требуется повторная обработка известного формата CSV (или любого другого), я пишупростой анализатор.

Кажется, что ваша проблема подходит ко второй категории, и анализатор должен быть очень простым:

f = open('file.txt', 'r').readlines()
for line in f:
 tokens = line.strip().split('\t')
 gene = tokens[0]
 vals = [float(k) for k in tokens[1:10]]
 stuff = tokens[10:]
 # do something with gene, vals, and stuff

Вы можете добавить строку в ридер для пропуска комментариевif tokens [0] == '#': continue ') или для обработки пустых строк (' if tokens == []: continue ').Вы поняли.

0 голосов
/ 18 мая 2010

Вероятно, оно пришло из строки 27100 в вашем файле данных ... и в нем было 12 столбцов вместо 16. Т.е. оно имело:

separator,1,2,3,4,5,6,7,8,9,10,11,12,separator

И ожидалось что-то вроде этого:

separator,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,separator

Я не уверен, как вы хотите конвертировать ваши данные, но если у вас неправильная длина строки, самый простой способ будет выглядеть примерно так:

lines = f.read().split('someseparator')
for line in lines:
    splitline = line.split(',')
    #do something with splitline
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...