获取numpy ndarray的描述性统计

2024-04-27 14:10:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用以下代码创建一个numpy ndarray。该文件有9列。我显式键入每个列:

dataset = np.genfromtxt("data.csv", delimiter=",",dtype=('|S1', float, float,float,float,float,float,float,int))

现在我想得到每一列的描述性统计数据(最小值、最大值、标准偏差、平均值、中位数等)。难道不应该有一个简单的方法来做这件事吗?

我试过这个:

from scipy import stats
stats.describe(dataset)

但这会返回一个错误:TypeError: cannot perform reduce with flexible type

我的问题是:如何获取创建的numpy ndarray的描述性统计数据。


Tags: 文件csv代码numpydata键入statsnp
2条回答

这不是一个很好的解决方案,但它能完成任务。问题是,通过指定多个数据类型,您实际上是在生成元组的1D数组(实际上是np.void),因为它包含多个不同的类型(包括字符串),所以stats无法对其进行描述。

这可以通过两轮阅读或者使用pandas和^{}来解决。

如果你决定坚持numpy

import numpy as np
a = np.genfromtxt('sample.txt', delimiter=",",unpack=True,usecols=range(1,9))
s = np.genfromtxt('sample.txt', delimiter=",",unpack=True,usecols=0,dtype='|S1')

from scipy import stats
for arr in a: #do not need the loop at this point, but looks prettier
    print(stats.describe(arr))
#Output per print:
DescribeResult(nobs=6, minmax=(0.34999999999999998, 0.70999999999999996), mean=0.54500000000000004, variance=0.016599999999999997, skewness=-0.3049304880932534, kurtosis=-0.9943046886340534)

注意,在这个例子中,最终数组有dtype作为float,而不是int,但是可以很容易(如果需要)使用arr.astype(int)转换为int

如何处理来自genfromtxt的混合数据的问题经常出现。人们期望一个二维数组,却得到一个不能按列索引的一维数组。这是因为他们得到了一个结构化数组——每列有不同的数据类型。

文档中的所有示例都显示如下:

>>> s = StringIO("1,1.3,abcde")
>>> data = np.genfromtxt(s, dtype=[('myint','i8'),('myfloat','f8'),
... ('mystring','S5')], delimiter=",")
>>> data
array((1, 1.3, 'abcde'),
      dtype=[('myint', '<i8'), ('myfloat', '<f8'), ('mystring', '|S5')])

但是让我演示一下如何访问这种数据

In [361]: txt=b"""A, 1,2,3
     ...: B,4,5,6
     ...: """
In [362]: data=np.genfromtxt(txt.splitlines(),delimiter=',',dtype=('S1,int,float,int'))
In [363]: data
Out[363]: 
array([(b'A', 1, 2.0, 3), (b'B', 4, 5.0, 6)], 
      dtype=[('f0', 'S1'), ('f1', '<i4'), ('f2', '<f8'), ('f3', '<i4')])

所以我的数组有两条记录(检查形状),它们在列表中显示为元组。

访问fields是按名称,而不是按列号(是否需要添加结构化数组文档链接?)

In [364]: data['f0']
Out[364]: 
array([b'A', b'B'], 
      dtype='|S1')
In [365]: data['f1']
Out[365]: array([1, 4])

在这种情况下,如果我选择带“子阵”的dtype可能更有用。这是一个更高级的数据类型主题

In [367]: data=np.genfromtxt(txt.splitlines(),delimiter=',',dtype=('S1,(3)float'))
In [368]: data
Out[368]: 
array([(b'A', [1.0, 2.0, 3.0]), (b'B', [4.0, 5.0, 6.0])], 
      dtype=[('f0', 'S1'), ('f1', '<f8', (3,))])
In [369]: data['f1']
Out[369]: 
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])

character列仍作为S1加载,但数字现在位于3列数组中。注意,它们都是float(或int)。

In [371]: from scipy import stats
In [372]: stats.describe(data['f1'])
Out[372]: DescribeResult(nobs=2, 
   minmax=(array([ 1.,  2.,  3.]), array([ 4.,  5.,  6.])),
   mean=array([ 2.5,  3.5,  4.5]), 
   variance=array([ 4.5,  4.5,  4.5]), 
   skewness=array([ 0.,  0.,  0.]), 
   kurtosis=array([-2., -2., -2.]))

相关问题 更多 >