我们接着《Python数据分析之numpy学习(一)》继续讲解有关numpy方面的知识! 统计函数与线性代数运算 统计运算中常见的聚合函数有:最小值、最大值、中位数、均值、方差、标准差等。首先来看看数组元素级别的计算: In [94]: arr11 = 5-np.arange(1,13).reshape(4,3) In [95]: arr12 = np.random.randint(1,10,size = 12).reshape(4,3) In [96]: arr11 Out[96]: array([[ 4, 3, 2], [ 1, 0, -1], [-2, -3, -4], [-5, -6, -7]]) In [97]: arr12 Out[97]: array([[1, 3, 7], [7, 3, 7], [3, 7, 4], [6, 1, 2]]) In [98]: arr11 ** 2 #计算每个元素的平方 Out[98]: array([[16, 9, 4], [ 1, 0, 1], [ 4, 9, 16], [25, 36, 49]]) In [99]: np.sqrt(arr11) #计算每个元素的平方根 Out[99]: array([[ 2. , 1.73205081, 1.41421356], [ 1. , 0. , nan], [ nan, nan, nan], [ nan, nan, nan]]) 由于负值的平方根没有意义,故返回nan。 In [100]: np.exp(arr11) #计算每个元素的指数值 Out[100]: array([[ 5.45981500e+01, 2.00855369e+01, 7.38905610e+00], [ 2.71828183e+00, 1.00000000e+00, 3.67879441e-01], [ 1.35335283e-01, 4.97870684e-02, 1.83156389e-02], [ 6.73794700e-03, 2.47875218e-03, 9.11881966e-04]]) In [101]: np.log(arr12) #计算每个元素的自然对数值 Out[101]: array([[ 0. , 1.09861229, 1.94591015], [ 1.94591015, 1.09861229, 1.94591015], [ 1.09861229, 1.94591015, 1.38629436], [ 1.79175947, 0. , 0.69314718]]) In [102]: np.abs(arr11) #计算每个元素的绝对值 Out[102]: array([[4, 3, 2], [1, 0, 1], [2, 3, 4], [5, 6, 7]]) 相同形状数组间元素的操作: In [103]: arr11 + arr12 #加 Out[103]: array([[ 5, 6, 9], [ 8, 3, 6], [ 1, 4, 0], [ 1, -5, -5]]) In [104]: arr11 - arr12 #减 Out[104]: array([[ 3, 0, -5], [ -6, -3, -8], [ -5, -10, -8], [-11, -7, -9]]) In [105]: arr11 * arr12 #乘 Out[105]: array([[ 4, 9, 14], [ 7, 0, -7], [ -6, -21, -16], [-30, -6, -14]]) In [106]: arr11 / arr12 #除 Out[106]: array([[ 4. , 1. , 0.28571429], [ 0.14285714, 0. , -0.14285714], [-0.66666667, -0.42857143, -1. ], [-0.83333333, -6. , -3.5 ]]) In [107]: arr11 // arr12 #整除 Out[107]: array([[ 4, 1, 0], [ 0, 0, -1], [-1, -1, -1], [-1, -6, -4]], dtype=int32) In [108]: arr11 % arr12 #取余 Out[108]: array([[0, 0, 2], [1, 0, 6], [1, 4, 0], [1, 0, 1]], dtype=int32) 接下来我们看看统计运算函数: In [109]: np.sum(arr11) #计算所有元素的和 Out[109]: -18 In [110]: np.sum(arr11,axis = 0) #对每一列求和 Out[110]: array([ -2, -6, -10]) In [111]: np.sum(arr11, axis = 1) #对每一行求和 Out[111]: array([ 9, 0, -9, -18]) In [112]: np.cumsum(arr11) #对每一个元素求累积和(从上到下,从左到右的元素顺序) Out[112]: array([ 4, 7, 9, 10, 10, 9, 7, 4, 0, -5, -11, -18], dtype=int32) In [113]: np.cumsum(arr11, axis = 0) #计算每一列的累积和,并返回二维数组 Out[113]: array([[ 4, 3, 2], [ 5, 3, 1], [ 3, 0, -3], [ -2, -6, -10]], dtype=int32) In [114]: np.cumprod(arr11, axis = 1) #计算每一行的累计积,并返回二维数组 Out[114]: array([[ 4, 12, 24], [ 1, 0, 0], [ -2, 6, -24], [ -5, 30, -210]], dtype=int32) In [115]: np.min(arr11) #计算所有元素的最小值 Out[115]: -7 In [116]: np.max(arr11, axis = 0) #计算每一列的最大值 Out[116]: array([4, 3, 2]) In [117]: np.mean(arr11) #计算所有元素的均值 Out[117]: -1.5 In [118]: np.mean(arr11, axis = 1) #计算每一行的均值 Out[118]: array([ 3., 0., -3., -6.]) In [119]: np.median(arr11) #计算所有元素的中位数 Out[119]: -1.5 In [120]: np.median(arr11, axis = 0) #计算每一列的中位数 Out[120]: array([-0.5, -1.5, -2.5]) In [121]: np.var(arr12) #计算所有元素的方差 Out[121]: 5.354166666666667 In [122]: np.std(arr12, axis = 1) #计算每一行的标准差 Out[122]: array([ 2.49443826, 1.88561808, 1.69967317, 2.1602469 ]) numpy中的统计函数运算是非常灵活的,既可以计算所有元素的统计值,也可以计算指定行或列的统计指标。还有其他常用的函数,如符号函数sign,ceil(>=x的最小整数),floor(<> 让我很兴奋的一个函数是where(),它类似于Excel中的if函数,可以进行灵活的变换: In [123]: arr11 Out[123]: array([[ 4, 3, 2], [ 1, 0, -1], [-2, -3, -4], [-5, -6, -7]]) In [124]: np.where(arr11 < 0,=""> Out[124]: array([['positive', 'positive', 'positive'], ['positive', 'positive', 'negtive'], ['negtive', 'negtive', 'negtive'], ['negtive', 'negtive', 'negtive']], dtype='<> 当然,np.where还可以嵌套使用,完成复杂的运算。 其它函数 unique(x):计算x的唯一元素,并返回有序结果 intersect(x,y):计算x和y的公共元素,即交集 union1d(x,y):计算x和y的并集 setdiff1d(x,y):计算x和y的差集,即元素在x中,不在y中 setxor1d(x,y):计算集合的对称差,即存在于一个数组中,但不同时存在于两个数组中 in1d(x,y):判断x的元素是否包含于y中 线性代数运算 同样numpu也跟R语言一样,可以非常方便的进行线性代数方面的计算,如行列式、逆、迹、特征根、特征向量等。但需要注意的是,有关线性代数的函数并不在numpy中,而是numpy的子例linalg中。 In [125]: arr13 = np.array([[1,2,3,5],[2,4,1,6],[1,1,4,3],[2,5,4,1]]) In [126]: arr13 Out[126]: array([[1, 2, 3, 5], [2, 4, 1, 6], [1, 1, 4, 3], [2, 5, 4, 1]]) In [127]: np.linalg.det(arr13) #返回方阵的行列式 Out[127]: 51.000000000000021 In [128]: np.linalg.inv(arr13) #返回方阵的逆 Out[128]: array([[-2.23529412, 1.05882353, 1.70588235, -0.29411765], [ 0.68627451, -0.25490196, -0.7254902 , 0.2745098 ], [ 0.19607843, -0.21568627, 0.07843137, 0.07843137], [ 0.25490196, 0.01960784, -0.09803922, -0.09803922]]) In [129]: np.trace(arr13) #返回方阵的迹(对角线元素之和),注意迹的求解不在linalg子例程中 Out[129]: 10 In [130]: np.linalg.eig(arr13) #返回由特征根和特征向量组成的元组 Out[130]: (array([ 11.35035004, -3.99231852, -0.3732631 , 3.01523159]), array([[-0.4754174 , -0.48095078, -0.95004728, 0.19967185], [-0.60676806, -0.42159999, 0.28426325, -0.67482638], [-0.36135292, -0.16859677, 0.08708826, 0.70663129], [-0.52462832, 0.75000995, 0.09497472, -0.07357122]])) In [131]: np.linalg.qr(arr13) #返回方阵的QR分解 Out[131]: (array([[-0.31622777, -0.07254763, -0.35574573, -0.87645982], [-0.63245553, -0.14509525, 0.75789308, -0.06741999], [-0.31622777, -0.79802388, -0.38668014, 0.33709993], [-0.63245553, 0.580381 , -0.38668014, 0.33709993]]), array([[-3.16227766, -6.64078309, -5.37587202, -6.95701085], [ 0. , 1.37840488, -1.23330963, -3.04700025], [ 0. , 0. , -3.40278524, 1.22190924], [ 0. , 0. , 0. , -3.4384193 ]])) In [132]:np.linalg.svd(arr13) #返回方阵的奇异值分解 Out[132]: (array([[-0.50908395, 0.27580803, 0.35260559, -0.73514132], [-0.59475561, 0.4936665 , -0.53555663, 0.34020325], [-0.39377551, -0.10084917, 0.70979004, 0.57529852], [-0.48170545, -0.81856751, -0.29162732, -0.11340459]]), array([ 11.82715609, 4.35052602, 3.17710166, 0.31197297]), array([[-0.25836994, -0.52417446, -0.47551003, -0.65755329], [-0.10914615, -0.38326507, -0.54167613, 0.74012294], [-0.18632462, -0.68784764, 0.69085326, 0.12194478], [ 0.94160248, -0.32436807, -0.05655931, -0.07050652]])) In [133]: np.dot(arr13,arr13) #方阵的正真乘积运算 Out[133]: array([[18, 38, 37, 31], [23, 51, 38, 43], [13, 25, 32, 26], [18, 33, 31, 53]]) In [134]:arr14 = np.array([[1,-2,1],[0,2,-8],[-4,5,9]]) In [135]: vector = np.array([0,8,-9]) In [136]: np.linalg.solve(arr14,vector) Out[136]: array([ 29., 16., 3.]) 随机数生成 统计学中经常会讲到数据的分布特征,如正态分布、指数分布、卡方分布、二项分布、泊松分布等,下面就讲讲有关分布的随机数生成。 正态分布直方图 In [137]: import matplotlib #用于绘图的模块 In [138]: np.random.seed(1234) #设置随机种子 In [139]: N = 10000 #随机产生的样本量 In [140]: randnorm = np.random.normal(size = N) #生成正态随机数 In [141]: counts, bins, path = matplotlib.pylab.hist(randnorm, bins = np.sqrt(N), normed = True, color = 'blue') #绘制直方图 以上将直方图的频数和组距存放在counts和bins内。 In [142]: sigma = 1; mu = 0 In [143]: norm_dist = (1/np.sqrt(2*sigma*np.pi))*np.exp(-((bins-mu)**2)/2) #正态分布密度函数 In [144]: matplotlib.pylab.plot(bins,norm_dist,color = 'red') #绘制正态分布密度函数图 使用二项分布进行赌博 同时抛弃9枚硬币,如果正面朝上少于5枚,则输掉8元,否则就赢8元。如果手中有1000元作为赌资,请问赌博10000次后可能会是什么情况呢? In [146]: np.random.seed(1234) In [147]: binomial = np.random.binomial(9,0.5,10000) #生成二项分布随机数 In [148]: money = np.zeros(10000) #生成10000次赌资的列表 In [149]: money[0] = 1000 #首次赌资为1000元 In [150]: for i in range(1,10000): ...: if binomial[i] <> ...: money[i] = money[i-1] - 8 #如果少于5枚正面,则在上一次赌资的基础上输掉8元 ...: else: ...: money[i] = money[i-1] + 8 #如果至少5枚正面,则在上一次赌资的基础上赢取8元 In [151]: matplotlib.pylab.plot(np.arange(10000), money) 使用随机整数实现随机游走 一个醉汉在原始位置上行走10000步后将会在什么地方呢?如果他每走一步是随机的,即下一步可能是1也可能是-1。 In [152]: np.random.seed(1234) #设定随机种子 In [153]: position = 0 #设置初始位置 In [154]: walk = [] #创建空列表 In [155]: steps = 10000 #假设接下来行走10000步 In [156]: for i in np.arange(steps): ...: step = 1 if np.random.randint(0,2) else -1 #每一步都是随机的 ...: position = position + step #对每一步进行累计求和 ...: walk.append(position) #确定每一步所在的位置 In [157]: matplotlib.pylab.plot(np.arange(10000), walk) #绘制随机游走图 上面的代码还可以写成(结合前面所讲的where函数,cumsum函数): In [158]: np.random.seed(1234) In [159]: step = np.where(np.random.randint(0,2,10000)>0,1,-1) In [160]: position = np.cumsum(step) In [161]: matplotlib.pylab.plot(np.arange(10000), position)
使用Python进行数据分析,一般都会使用到numpy,pandas,scipy和matplotlib等模块,而numpy是最为基础的模块,其他模块的使用都是以numpy为核心,所以这里讲解了有关numpy的方方面面,这部分的学习非常重要,希望感兴趣的朋友多看看这方面的文档和动手操作。在接下来Python一期中将会讲到pandas模块的学习。 |
|