【问题标题】:Normalize/Standardize a numpy recarray规范化/标准化一个 numpy recarray
【发布时间】:2012-04-04 06:26:49
【问题描述】:

我想知道规范化/标准化 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())

还有更优雅的方法吗?是否有某种方法,例如“规范化”或“标准化”?

【问题讨论】:

    标签: python numpy scipy normalize recarray


    【解决方案1】:

    有很多方法可以做到这一点,但有些方法比其他方法更干净。

    通常,在 numpy 中,您将字符串数据保存在单独的数组中。

    (事物比 R 的数据框要低级一些。您通常只需将事物包装在一个类中以进行关联,但将不同的数据类型分开。)

    老实说,numpy 并未针对处理诸如此类的“灵活”数据类型进行优化(尽管它当然可以做到)。 pandas 之类的东西为“电子表格式”数据提供了更好的接口(而 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 谢谢。这是一个非常翔实和有见地的答案。将数据集拆分为数字列和非数字列可能是要走的路。这使得许多其他操作定义明确,实际上是我试图做的。我不知道使用data[list] 选择多个列的选项。
    【解决方案2】:

    您使用的是哪个版本的 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
    

    我只是想知道您的数据有什么不同。

    【讨论】:

    • 注意:这是作为评论,而不是答案......只是需要更多空间来放置上面的示例。
    • 不同的是你得到的是一个字符串数组,而不是一个结构化数组。在您的示例中查看 a 的 dtype。
    • 当然,但是是什么导致传入的数组是“结构化的”?如果只是一个csv文件,genfromtxt()不会总是产生一个字符串数组吗?
    • 不。在您的情况下,它只是创建一个字符串数组,因为第一行(列名)都是字符串。如果您在第一行的任何列中有数字,您将获得一个结构化数组。在您的情况下,如果您指定names=True,则将从第一行读取列名,您将获得一个结构化数组。 (顺便说一下,我所说的“结构化”,请参阅here
    • @JoeKington 可能有所不同。我有四个要标准化的纯数字列,一个带有标签。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 2021-02-16
    • 2016-02-04
    • 1970-01-01
    • 2023-01-20
    • 2018-04-05
    • 1970-01-01
    相关资源
    最近更新 更多