2015-04-04 2 views
1

У меня есть данные вида:Почему np.genfromtxt() удаляет заголовок при импорте в Python?

#--------------------- 
# Data 
#--------------------- 
p q r y 1 y 2 y 3 y 4 
2 8 14 748 748 748 790 
2 9 22 262 245 252 328 
1 5 19 512 514 511 569 
2 7 19 748 748 748 805 
3 11 13 160 168 108 164 
2 7 20 788 788 788 848 
1 4 15 310 310 310 355 
3 12 17 230 210 213 218 

И я пытаюсь создать массив B с помощью np.genfromtxt(), используя код:

import numpy as np 
A = open('data.dat', "r") 
line = A.readline() 
while line.startswith('#'): 
    line = A.readline() 
A_header = line.split("\t") 
A_header[-1] = A_header[-1].strip() 
B = np.genfromtxt('data.dat', comments='#', delimiter='\t', names = A_header, dtype = None, unpack = True).transpose() 
print B 
print B['y_1'] 

У меня есть два вопроса:

  1. Почему np.genfromtxt() не удаляет заголовок данных при импорте? Когда данные импортируются массив B все еще имеет заголовок P, Q, ... у 3, у 4.

  2. Почему мы должны обеспечить подчеркивания для имен заголовков, например y_1, y_2 и т. д.? Почему мы не можем указывать имена, поскольку это y 1, y 2 ... y 4?

ответ

2

Вместо того, чтобы открыть файл в два раза, что о:

import numpy as np 

with open('input.txt', "r") as data: 
    while True: 
     line = data.readline() 
     if not line.startswith('#'): break 

    header = [e for e in line.strip().split('\t') if e] 
    print(header) 

    B = np.genfromtxt(data, names=header, dtype=None, delimiter='\t') 

print B 
print B['y_1'] 

Выход:

# header 
['p', 'q', 'r', 'y 1', 'y 2', 'y 3', 'y 4'] 

# B 
[(2, 8, 14, 748, 748, 748, 790) (2, 9, 22, 262, 245, 252, 328) 
(1, 5, 19, 512, 514, 511, 569) (2, 7, 19, 748, 748, 748, 805) 
(3, 11, 13, 160, 168, 108, 164) (2, 7, 20, 788, 788, 788, 848) 
(1, 4, 15, 310, 310, 310, 355) (3, 12, 17, 230, 210, 213, 218)] 

# B['y_1'] 
[748 262 512 748 160 788 310 230] 

Вместо того чтобы передавать имя файла для np.genfromtxt, здесь, вы передаете data читателя файл генератор.

В противном случае вы попадаете в странную ситуацию, когда skip_header не работает, потому что он рассматривает строки комментариев. Таким образом, вы должны сказать skip_header=4 (3 строки комментариев + 1 строка заголовка), когда что составляет skip_header=1.

Таким образом, этот подход сначала «выкидывает» строки комментариев. Затем для следующей строки извлекаются заголовки. Он передает оставшиеся строки в функцию np.genfromtxt с соответствующими заголовками.

Несколько замечаний:

  • unpack=True + transpose() компенсируют друг друга. Таким образом, эффект от использования обоих методов аналогичен использованию. Поэтому не используйте их.

  • И если вы действительно хотите, чтобы получить доступ к полям, используя имена с пробелами (вместо подчеркивания), вы всегда можете переименовать поля после генерации ndarray:

    B.dtype.names = [n.replace('_', ' ') for n in B.dtype.names] 
    print B['y 1'] # [748 262 512 748 160 788 310 230] 
    
0

Ваш формат борется пара предположений, что genfromtxt делает:

1) у вас есть и строка комментариев и строка заголовка (без символа #)

2) имена ваших колонок имеют пробелы, которые genfromtxt настаивает на преобразовании в _ (или какой-либо другой допустимый символ).

Если я создаю текстовый файл с образцом, и заменить пробелы с закладками (который является боль, тем более, что мои редакторы настроены заменить вкладки с пробелами), это работает:

In [330]: np.genfromtxt('stack29451030.txt',delimiter='\t',dtype=None,skip_header=3,names=True) 
Out[330]: 
array([(2, 8, 14, 748, 748, 748, 790), (2, 9, 22, 262, 245, 252, 328)], 
     dtype=[('p', '<i4'), ('q', '<i4'), ('r', '<i4'), ('y_1', '<i4'), ('y_2', '<i4'), ('y_3', '<i4'), ('y_4', '<i4')]) 

я играл с replace_space=' '. Похоже, что он использует только замены, которые создают допустимые имена переменных и атрибутов Python. Итак, 'y_1' в порядке, но не 'y 1 '. Я не вижу способа использования параметров.

comments и names не сотрудничают в вашем случае. Он может пропускать строки комментариев, но затем будет читать строку имен в качестве данных.

In [350]: np.genfromtxt('stack29451030.txt',delimiter='\t',dtype=None,comments='#') 
Out[350]: 
array([['p', 'q', 'r', 'y 1', 'y 2', 'y 3', 'y 4'], 
     ['2', '8', '14', '748', '748', '748', '790'], 
     ['2', '9', '22', '262', '245', '252', '328']], 
     dtype='|S3') 

Он может обрабатывать строку названия как #p q r y1 y2 y3 y4, не обращая внимания на #, но тогда он не пропускает ранее комментарии линий. Поэтому, если вы можете удалить строки комментариев или строку заголовка, он сможет ее прочитать. Но похоже, что вы должны использовать что-то другое, кроме comments.

Это выглядит как самая чистая нагрузка - явно пропускают 1-ю 3 строки, принимают строку заголовка, а затем используют идею jedwards's для замены _.

In [396]: A=np.genfromtxt('stack29451030.txt',delimiter='\t',dtype=None,skip_header=3,names=True) 

In [397]: A.dtype.names = [n.replace('_', ' ') for n in A.dtype.names] 

In [398]: A 
Out[398]: 
array([(2, 8, 14, 748, 748, 748, 790), (2, 9, 22, 262, 245, 252, 328)], 
     dtype=[('p', '<i4'), ('q', '<i4'), ('r', '<i4'), ('y 1', '<i4'), ('y 2', '<i4'), ('y 3', '<i4'), ('y 4', '<i4')]) 

Если вы не знаете, сколько комментариев строк есть, этот генератор может фильтровать их:

with open('stack29451030.txt') as f: 
    g = (line for line in f if not line.startswith('#')) 
    A = np.genfromtxt(g, delimiter='\t', names=True, dtype=None) 

genfromtxt принимает входные данные от любой итерации, будь то файл, список строк, или генератора, подобного этому.

0

Для чего это стоит pandas.read_table этот файл легко читается.

import pandas 
B = pandas.read_table('data.dat', comment='#') 

print B['y 1'] # Note the space is retained in the column name 
+0

Он работает, если вы публикуете комментарии в файле данных. У меня всегда есть комментарии в файле данных, и из-за этого я использовал comment = '#', но он не работает. –

+0

Извините, я играл с файлом данных и удалял комментарии. Я обновил для правильного чтения. Это отлично работает на моей стороне. – chthonicdaemon

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