如何获取NumPy数组的描述性统计信息?

lsmepo6l  于 2023-04-21  发布在  其他
关注(0)|答案(5)|浏览(123)

我使用以下代码创建一个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数组的描述性统计信息?

jc3wubiy

jc3wubiy1#

import pandas as pd
import numpy as np

df_describe = pd.DataFrame(dataset)
df_describe.describe()

请注意,dataset是要描述的np.array。

import pandas as pd
import numpy as np

df_describe = pd.DataFrame('your np.array')
df_describe.describe()
zvms9eto

zvms9eto2#

这不是一个漂亮的解决方案,但它完成了工作。问题是,通过指定多个dtypes,你本质上是在制作一个元组的1D数组(实际上是np.void),它不能用stats描述,因为它包含多个不同的类型,包括字符串。
这可以通过分两轮阅读来解决,或者使用pandas和read_csv
如果您决定坚持使用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)

请注意,在本例中,最终数组的dtypefloat,而不是int,但可以轻松地(如果需要)使用arr.astype(int)转换为int

t3irkdon

t3irkdon3#

如何处理来自genfromtxt的混合数据的问题经常出现。人们期望一个2d数组,而不是得到一个不能按列索引的1d数组。这是因为他们得到的是一个结构化数组-每个列都有不同的dtype。
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])

在这种情况下,如果我选择一个带有'subarrays'的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.]])

字符列仍然作为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.]))
fkvaft9z

fkvaft9z4#

官方Scipy文档Example

#INPUT
from scipy import stats
a = np.arange(10)
stats.describe(a)

#OUTPUT
DescribeResult(nobs=10, minmax=(0, 9), mean=4.5, variance=9.166666666666666,
               skewness=0.0, kurtosis=-1.2242424242424244)

#INPUT
b = [[1, 2], [3, 4]]
stats.describe(b)

#OUTPUT
DescribeResult(nobs=2, minmax=(array([1, 2]), array([3, 4])),
               mean=array([2., 3.]), variance=array([2., 2.]),
               skewness=array([0., 0.]), kurtosis=array([-2., -2.]))
1hdlvixo

1hdlvixo5#

对于那些需要快速计算的人来说,scipy + numpy比pandas更快:

# scipy + numpy
def get_stats(v):
    res = stats.describe(v)
    return np.concatenate([
        [
            res.minmax[0],
            res.minmax[1],
            res.mean,
            res.variance,
            res.skewness,
            res.kurtosis
        ],
        np.percentile(v, q=[10, 25, 50, 75, 90])
    ])
%timeit get_stats(np.arange(100))
639 µs ± 11.3 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

%timeit pd.Series(np.arange(100)).describe(percentiles=[0.1, 0.25, 0.5, 0.75, 0.9])
830 µs ± 31.1 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

加上在describe() pandas中没有提取 * 峰度 * 和 * 偏度 *

警告:使用pd.DataFrame(array).describe()速度较慢:

%timeit pd.DataFrame(np.arange(100)).describe(percentiles=[0.1, 0.25, 0.5, 0.75, 0.9])
1.43 ms ± 75.6 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

相关问题