我想知道正常化/标准化numpy recarray
的最佳方法是什么。
为了说清楚,我不是在谈论一个数学矩阵,而是一个记录数组,它也有例如文本列(例如标签)。
a = np.genfromtxt("iris.csv", delimiter=",", dtype=None)
print a.shape
> (150,)
正如你所看到的,我不能,例如处理a[:,:-1]
,因为形状是一维的。
我发现最好的是迭代所有列:
for nam in a.dtype.names[:-1]:
col = a[nam]
a[nam] = (col - col.min()) / (col.max() - col.min())
更优雅的方式吗?是否有某些方法,如“标准化”或“标准化”某处?
答案 0 :(得分:7)
有很多方法可以做到,但有些方法比其他方法更清洁。
通常,在numpy中,将字符串数据保存在单独的数组中。
(事情比R的数据框要低一些。你通常只是在一个类中包含关联,但保持不同的数据类型分开。)
老实说,numpy并没有针对处理这种“灵活”数据类型进行优化(虽然它肯定可以做到)。 pandas
之类的东西为“类似电子表格”的数据提供了更好的界面(而且大熊猫只是numpy之上的一层)。
但是,当您传入字段名称列表时,结构化数组(这里是您所拥有的)将允许您按列进行切片。 (例如data[['col1', 'col2', 'col3']]
)
无论如何,一种方法是做这样的事情:
import numpy as np
data = np.recfromcsv('iris.csv')
# In this case, it's just all but the last, but we could be more general
# This must be a list and not a tuple, though.
float_fields = list(data.dtype.names[:-1])
float_dat = data[float_fields]
# Now we just need to view it as a "regular" 2D array...
float_dat = float_dat.view(np.float).reshape((data.size, -1))
# And we can normalize columns as usual.
normalized = (float_dat - float_dat.min(axis=0)) / float_dat.ptp(axis=0)
然而,这远非理想。如果你想就地进行操作(就像你现在的那样),最简单的解决方案就是你已经拥有的:只需迭代字段名称即可。
顺便说一句,使用pandas
,您可以执行以下操作:
import pandas
data = pandas.read_csv('iris.csv', header=None)
float_dat = data[data.columns[:-1]]
dmin, dmax = float_dat.min(axis=0), float_dat.max(axis=0)
data[data.columns[:-1]] = (float_dat - dmin) / (dmax - dmin)
答案 1 :(得分:1)
您使用的是哪种版本的NumPy?在1.5.1版本中,我没有得到这种行为。我以短文本文件为例,保存为test.txt
:
last,first,country,state,zip
tyson,mike,USA,Nevada,89146
brady,tom,USA,Massachusetts,02035
当我执行以下代码时,这就是我得到的:
>>> import numpy as np
>>> a = np.genfromtxt("/home/ely/Desktop/Python/test.txt",delimiter=',',dtype=None)
>>> print a.shape
(3,5)
>>> print a
[['last' 'first' 'country' 'state' 'zip']
['tyson' 'mike' 'USA' 'Nevada' '89146']
['brady' 'tom' 'USA' 'Massachusetts' '02035']]
>>> print a[0,:-1]
['last' 'first' 'country' 'state']
>>> print a.dtype.names
None
我只是想知道你的数据有什么不同。