Как использовать numpy.genfromtxt, когда первый столбец является строкой, а остальные столбцы - номерами?
В принципе, у меня есть куча данных, где первый столбец является строкой (меткой), а остальные столбцы - числовыми. Я запускаю следующее:
data = numpy.genfromtxt('data.txt', delimiter = ',')
Это хорошо читает большинство данных, но столбец ярлыков просто получает "nan". Как я могу справиться с этим?
Ответы
Ответ 1
По умолчанию np.genfromtxt
использует dtype=float
: почему строковые столбцы преобразуются в NaN, потому что, в конце концов, они не являются числом...
Вы можете попросить np.genfromtxt
попытаться угадать фактический тип столбцов с помощью dtype=None
:
>>> from StringIO import StringIO
>>> test = "a,1,2\nb,3,4"
>>> a = np.genfromtxt(StringIO(test), delimiter=",", dtype=None)
>>> print a
array([('a',1,2),('b',3,4)], dtype=[('f0', '|S1'),('f1', '<i8'),('f2', '<i8')])
Вы можете получить доступ к столбцам, используя их имя, например a['f0']
...
Использование dtype=None
- хороший трюк, если вы не знаете, какими должны быть ваши столбцы. Если вы уже знаете, какой тип они должны иметь, вы можете указать явный dtype
. Например, в нашем тесте мы знаем, что первый столбец является строкой, второй - int, и мы хотим, чтобы третий был float. Тогда мы использовали бы
>>> np.genfromtxt(StringIO(test), delimiter=",", dtype=("|S10", int, float))
array([('a', 1, 2.0), ('b', 3, 4.0)],
dtype=[('f0', '|S10'), ('f1', '<i8'), ('f2', '<f8')])
Использование явного dtype
гораздо эффективнее, чем использование dtype=None
и является рекомендуемым способом.
В обоих случаях (dtype=None
или явный, неоднородный dtype
) вы получаете структурированный массив.
[Примечание: при dtype=None
вход обрабатывается второй раз, а тип каждого столбца обновляется, чтобы соответствовать большему типу: сначала мы пытаемся использовать bool, затем int, затем float, затем сложный, тогда мы сохраняем строку, если все остальное терпит неудачу. На самом деле реализация довольно сложная. Были некоторые попытки сделать угадывание типа более эффективным (с использованием regexp), но ничего не застряло до сих пор]
Ответ 2
Если ваш файл данных структурирован таким образом
col1, col2, col3
1, 2, 3
10, 20, 30
100, 200, 300
то numpy.genfromtxt
может интерпретировать первую строку как заголовки столбцов, используя опцию names=True
. Благодаря этому вы можете получить доступ к данным очень удобно, указав заголовок столбца:
data = np.genfromtxt('data.txt', delimiter=',', names=True)
print data['col1'] # array([ 1., 10., 100.])
print data['col2'] # array([ 2., 20., 200.])
print data['col3'] # array([ 3., 30., 300.])
Так как в вашем случае данные формируются следующим образом
row1, 1, 10, 100
row2, 2, 20, 200
row3, 3, 30, 300
вы можете добиться чего-то подобного, используя следующий фрагмент кода:
labels = np.genfromtxt('data.txt', delimiter=',', usecols=0, dtype=str)
raw_data = np.genfromtxt('data.txt', delimiter=',')[:,1:]
data = {label: row for label, row in zip(labels, raw_data)}
Первая строка считывает первый столбец (метки) в массив строк.
Вторая строка считывает все данные из файла, но отбрасывает первый столбец.
Третья строка использует понимание словаря для создания словаря, который можно использовать очень похоже на структурированный массив, который numpy.genfromtxt
создает с помощью опции names=True
:
print data['row1'] # array([ 1., 10., 100.])
print data['row2'] # array([ 2., 20., 200.])
print data['row3'] # array([ 3., 30., 300.])
Ответ 3
data=np.genfromtxt(csv_file, delimiter=',', dtype='unicode')
Это отлично работает для меня.
Ответ 4
Вы можете использовать numpy.recfromcsv(filename)
: типы каждого столбца будут автоматически определены (как если бы вы использовали np.genfromtxt()
с dtype=None
) и по умолчанию delimiter=","
. Это в основном ярлык для np.genfromtxt(filename, delimiter=",", dtype=None)
, на который указал Пьер ГМ в своем ответе.
Ответ 5
Для набора данных этого формата:
CONFIG000 1080.65 1080.87 1068.76 1083.52 1084.96 1080.31 1081.75 1079.98
CONFIG001 414.6 421.76 418.93 415.53 415.23 416.12 420.54 415.42
CONFIG010 1091.43 1079.2 1086.61 1086.58 1091.14 1080.58 1076.64 1083.67
CONFIG011 391.31 392.96 391.24 392.21 391.94 392.18 391.96 391.66
CONFIG100 1067.08 1062.1 1061.02 1068.24 1066.74 1052.38 1062.31 1064.28
CONFIG101 371.63 378.36 370.36 371.74 370.67 376.24 378.15 371.56
CONFIG110 1060.88 1072.13 1076.01 1069.52 1069.04 1068.72 1064.79 1066.66
CONFIG111 350.08 350.69 352.1 350.19 352.28 353.46 351.83 350.94
Этот код работает для моего приложения:
def ShowData(data, names):
i = 0
while i < data.shape[0]:
print(names[i] + ": ")
j = 0
while j < data.shape[1]:
print(data[i][j])
j += 1
print("")
i += 1
def Main():
print("The sample data is: ")
fname = 'ANOVA.csv'
csv = numpy.genfromtxt(fname, dtype=str, delimiter=",")
num_rows = csv.shape[0]
num_cols = csv.shape[1]
names = csv[:,0]
data = numpy.genfromtxt(fname, usecols = range(1,num_cols), delimiter=",")
print(names)
print(str(num_rows) + "x" + str(num_cols))
print(data)
ShowData(data, names)
Выход Python-2:
The sample data is:
['CONFIG000' 'CONFIG001' 'CONFIG010' 'CONFIG011' 'CONFIG100' 'CONFIG101'
'CONFIG110' 'CONFIG111']
8x9
[[ 1080.65 1080.87 1068.76 1083.52 1084.96 1080.31 1081.75 1079.98]
[ 414.6 421.76 418.93 415.53 415.23 416.12 420.54 415.42]
[ 1091.43 1079.2 1086.61 1086.58 1091.14 1080.58 1076.64 1083.67]
[ 391.31 392.96 391.24 392.21 391.94 392.18 391.96 391.66]
[ 1067.08 1062.1 1061.02 1068.24 1066.74 1052.38 1062.31 1064.28]
[ 371.63 378.36 370.36 371.74 370.67 376.24 378.15 371.56]
[ 1060.88 1072.13 1076.01 1069.52 1069.04 1068.72 1064.79 1066.66]
[ 350.08 350.69 352.1 350.19 352.28 353.46 351.83 350.94]]
CONFIG000:
1080.65
1080.87
1068.76
1083.52
1084.96
1080.31
1081.75
1079.98
CONFIG001:
414.6
421.76
418.93
415.53
415.23
416.12
420.54
415.42
CONFIG010:
1091.43
1079.2
1086.61
1086.58
1091.14
1080.58
1076.64
1083.67
CONFIG011:
391.31
392.96
391.24
392.21
391.94
392.18
391.96
391.66
CONFIG100:
1067.08
1062.1
1061.02
1068.24
1066.74
1052.38
1062.31
1064.28
CONFIG101:
371.63
378.36
370.36
371.74
370.67
376.24
378.15
371.56
CONFIG110:
1060.88
1072.13
1076.01
1069.52
1069.04
1068.72
1064.79
1066.66
CONFIG111:
350.08
350.69
352.1
350.19
352.28
353.46
351.83
350.94