NYC's Blog - Pandas http://niyanchun.com/tag/Pandas/ 如何修改Pandas中列的类型 http://niyanchun.com/how-to-change-column-data-type-in-pandas.html 2022-02-20T22:55:00+08:00 问题如题。一般pandas读取数据的时候,会自动检测数据的类型,但有时候可能不是特别准确,还需要我们自己做类型转换。比如下面这种:a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']] df = pd.DataFrame(a) df.dtypes # 0 object # 1 object # 2 object # dtype: object如何修改第2、3列的类型?扩展一下,如果有很多列的时候,如何高效的修改?​Pandas中主要有4种类型转换相关的方法:to_numeric/to_datetime/to_timedelta:可以参数转换为合适的对应类型。astypeinfer_objectsconvert_dtypesto_xxxto_numericto_numeric将参数转换为合适的数值类型(float64/int64)。签名如下:pandas.to_numeric(arg, errors='raise', downcast=None)先看一些使用例子:In [2]: s = pd.Series(["8", 6, "7.5", 3, "0.9"]) In [3]: s Out[3]: 0 8 1 6 2 7.5 3 3 4 0.9 dtype: object In [4]: pd.to_numeric(s) Out[4]: 0 8.0 1 6.0 2 7.5 3 3.0 4 0.9 dtype: float64可以使用apply()方法批量转换DataFrame里面的列:In [11]: df = pd.DataFrame([['1', '2', '3'],['4', '5', '6'],['7.1', '8.0', '9']], columns=['a','b', 'c']) In [12]: df Out[12]: a b c 0 1 2 3 1 4 5 6 2 7.1 8.0 9 In [13]: df.dtypes Out[13]: a object b object c object dtype: object In [14]: df_1=df.apply(pd.to_numeric) In [15]: df_1 Out[15]: a b c 0 1.0 2.0 3 1 4.0 5.0 6 2 7.1 8.0 9 In [16]: df_1.dtypes Out[16]: a float64 b float64 c int64 dtype: object也可以只对某些列进行转换:In [18]: df[['a','b']]=df[['a','b']].apply(pd.to_numeric) In [19]: df Out[19]: a b c 0 1.0 2.0 3 1 4.0 5.0 6 2 7.1 8.0 9 In [20]: df.dtypes Out[20]: a float64 b float64 c object dtype: object类型转换难免会产生错误,比如无法转换等,to_numeric提供了一个参数errors来让用户控制发生错误时如何处理,用有三个选项:'raise':默认值,即抛出异常'ignore':转换失败时,保留原值'coerce':转换失败时,设置为NaN看一些例子:In [21]: df=pd.DataFrame([['1','2'],['3','4'],['5','s']], columns=['a','b']) In [22]: df Out[22]: a b 0 1 2 1 3 4 2 5 s In [23]: df.dtypes Out[23]: a object b object dtype: object In [24]: df.apply(pd.to_numeric) ValueError: Unable to parse string "s" at position 2 In [25]: df.apply(pd.to_numeric, errors='coerce') Out[25]: a b 0 1 2.0 1 3 4.0 2 5 NaN In [26]: df.apply(pd.to_numeric, errors='ignore') Out[26]: a b 0 1 2 1 3 4 2 5 sto_numeric默认会转换为float64或者int64,如果你想节省内存转换为小一些的类型的话,可以使用to_numeric提供的downcast参数,可选值如下:'integer'或者'signed':转换为np.int8'unsigned':转换为np.uint8'float':转换为np.float32看一些例子:In [29]: s = pd.Series(['1','2','-7']) In [30]: s Out[30]: 0 1 1 2 2 -7 dtype: object In [31]: pd.to_numeric(s) Out[31]: 0 1 1 2 2 -7 dtype: int64 In [32]: pd.to_numeric(s, downcast='integer') Out[32]: 0 1 1 2 2 -7 dtype: int8 # 注意这里:因为 unsigned无法表示-7,所以这里实际没有发生downcast In [33]: pd.to_numeric(s, downcast='unsigned') Out[33]: 0 1 1 2 2 -7 dtype: int64 In [34]: pd.to_numeric(s, downcast='float') Out[34]: 0 1.0 1 2.0 2 -7.0 dtype: float32这里有2个注意点:downcast是发生在核心的类型转换之后的(也就是先将原始类型转换为float64/int64,然后再执行downcast动作),所以前面介绍的那个errors参数对downcast这里是无效的。如果目标类型无法容纳被转换的值,就不会发生实际的转换。比如上面尝试转换为'unsigned'类型时,因为-7无法转换为unsigned,所以实际没有执行downcast。to_datetimeto_datetime把参数转换为datetime类型,相比于to_numeric,函数原型复杂了一些。pandas.to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False, utc=None, format=None, exact=True, unit=None, infer_datetime_format=False, origin='unix', cache=True)看一些使用例子:# 可以使用这些关键字来构造表示时间日期的字典:[‘year’, ‘month’, ‘day’, ‘minute’, ‘second’, ‘ms’, ‘us’, ‘ns’]),复数也可以 In [35]: df = pd.DataFrame({'year': [2015, 2016], 'month': [2, 3], 'day':[4, 5]}) In [36]: df Out[36]:2015 2 42016 3 5In [37]: df.dtypesOut[37]:year int64month int64day int64dtype: objectIn [38]: pd.to_datetime(df)Out[38]:2015-02-042016-03-05dtype: datetime64[ns]In [40]: pd.to_datetime(1490195805, unit='s')Out[40]: Timestamp('2017-03-22 15:16:45')In [41]: pd.to_datetime(1490195805433502912, unit='ns')Out[41]: Timestamp('2017-03-22 15:16:45.433502912')In [42]: pd.to_datetime("10/11/12", dayfirst=True)Out[42]: Timestamp('2012-11-10 00:00:00')In [43]: pd.to_datetime("10/11/12", yearfirst=True)Out[43]: Timestamp('2010-11-12 00:00:00')In [44]: pd.to_datetime("10/11/12", dayfirst=True, yearfirst=True)Out[44]: Timestamp('2010-12-11 00:00:00')`errors`字段含义同`to_numeric`:'raise':默认值,即抛出异常'ignore':转换失败时,保留原值'coerce':转换失败时,设置为NaT。这里注意一种情况就是Pandas的时间精度是纳秒,且用int64表示,大概只能表示584年这样一个范围([pd.Timestamp.min, pd.Timestamp.max]),当转换的时间超出这个范围时也算失败。看个例子:In [46]: pd.Timestamp.min Out[46]: Timestamp('1677-09-21 00:12:43.145225') In [47]: pd.Timestamp.max Out[47]: Timestamp('2262-04-11 23:47:16.854775807') In [48]: pd.to_datetime('13000101', format='%Y%m%d', errors='raise') OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 1300-01-01 00:00:00 In [49]: pd.to_datetime('13000101', format='%Y%m%d', errors='ignore') Out[49]: datetime.datetime(1300, 1, 1, 0, 0) In [50]: pd.to_datetime('13000101', format='%Y%m%d', errors='coerce') Out[50]: NaT In [53]: pd.to_datetime('130000101', format='%Y%m%d', errors='ignore') Out[53]: '130000101'to_timedeltatimedelta类型表示两个时间的绝对差值,to_timedelta将参数转换为timedelta类型。方法签名如下:pandas.to_timedelta(arg, unit=None, errors='raise')unit用于指定参数的单位,默认为ns,合法的取值如下:‘W’‘D’ / ‘days’ / ‘day’‘hours’ / ‘hour’ / ‘hr’ / ‘h’‘m’ / ‘minute’ / ‘min’ / ‘minutes’ / ‘T’‘S’ / ‘seconds’ / ‘sec’ / ‘second’‘ms’ / ‘milliseconds’ / ‘millisecond’ / ‘milli’ / ‘millis’ / ‘L’‘us’ / ‘microseconds’ / ‘microsecond’ / ‘micro’ / ‘micros’ / ‘U’‘ns’ / ‘nanoseconds’ / ‘nano’ / ‘nanos’ / ‘nanosecond’ / ‘N’errors的取值同to_datetime。看几个使用例子:In [55]: pd.to_timedelta('1 days 06:05:01.00003') Out[55]: Timedelta('1 days 06:05:01.000030') In [56]: pd.to_timedelta('15.5us') Out[56]: Timedelta('0 days 00:00:00.000015500') In [57]: pd.to_timedelta(['1 days 06:05:01.00003', '15.5us', 'nan']) Out[57]: TimedeltaIndex(['1 days 06:05:01.000030', '0 days 00:00:00.000015500', NaT], dtype='timedelta64[ns]', freq=None) In [58]: import numpy as np In [59]: pd.to_timedelta(np.arange(5), unit='s') Out[59]: TimedeltaIndex(['0 days 00:00:00', '0 days 00:00:01', '0 days 00:00:02', '0 days 00:00:03', '0 days 00:00:04'], dtype='timedelta64[ns]', freq=None) In [60]: pd.to_timedelta(np.arange(5), unit='d') Out[60]: TimedeltaIndex(['0 days', '1 days', '2 days', '3 days', '4 days'], dtype='timedelta64[ns]', freq=None)astypeastype方法可以做任意类型的转换(当然未必能成功)。方法原型如下:pd.DataFrame.astype(dtype, copy=True, errors='raise')dtype就是我们想要转换成的目标类型,可以使用Numpy的类型、Python的部分类型、Pandas特有的类型。copy表示是否修改原数据。errors可以取'raise'(失败是抛异常)或者'ignore'(失败时忽略并返回原值)。​看一些例子:In [62]: df = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]}) In [63]: df.dtypes Out[63]: col1 int64 col2 int64 dtype: object In [64]: df.astype('int32').dtypes Out[64]: col1 int32 col2 int32 dtype: object In [65]: s = pd.Series([1, 3], dtype='int32') In [66]: s Out[66]: 0 1 1 3 dtype: int32 In [67]: s.astype('int64') Out[67]: 0 1 1 3 dtype: int64 In [68]: s.astype('category') Out[68]: 0 1 1 3 dtype: category Categories (2, int64): [1, 3] In [77]: s_date = pd.Series(['20220101', '20220102', '20220103']) In [78]: s_date Out[78]: 0 20220101 1 20220102 2 20220103 dtype: object In [79]: s_date.astype('datetime64') Out[79]: 0 2022-01-01 1 2022-01-02 2 2022-01-03 dtype: datetime64[ns] In [81]: i = pd.Series([1,2,3]) In [82]: i Out[82]: 0 1 1 2 2 3 dtype: int64 In [83]: i.astype(str) Out[83]: 0 1 1 2 2 3 dtype: object In [84]: s = pd.Series([1,2,-7]) In [85]: s.astype(np.int8) Out[85]: 0 1 1 2 2 -7 dtype: int8 In [86]: s.astype(np.uint8) Out[86]: 0 1 1 2 2 249 dtype: uint8使用astype的时候,要注意范围,比如下面的转换不会报错,但不是我们想要的:In [95]: s = pd.Series([1,2,-7]) # -7被转换为249 In [96]: s.astype(np.uint8) Out[96]: 0 1 1 2 2 249 dtype: uint8 # 使用to_numeric就不会有问题 In [97]: pd.to_numeric(s, downcast='unsigned') Out[97]: 0 1 1 2 2 -7 dtype: int64infer_objectspandas 0.21.0版本加入,会尝试推测类型。看个例子:In [103]: df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object') In [104]: df.dtypes Out[104]: a object b object dtype: object In [105]: df.infer_objects().dtypes Out[105]: a int64 b object dtype: object可以看到,infer_objects其实还是比较“肤浅”的,如果要将'b'列也转换成数值型,可以使用前面介绍的方法。convert_dtypesconvert_dtypes会尝试将各列转换为最可能的类型,其特点是支持pd.NA,方法签名如下:DataFrame.convert_dtypes(infer_objects=True, convert_string=True, convert_integer=True, convert_boolean=True, convert_floating=True)通过各个类型参数可以控制某些类型是否转换;infer_objects为True时会尝试转换object类型为更具体的类型。看一些例子:In [110]: df = pd.DataFrame( ...: { ...: 'a': pd.Series([1, 2, 3], dtype=np.dtype('int32')), ...: 'b': pd.Series(['x', 'y', 'z'], dtype=np.dtype('O')), ...: 'c': pd.Series([True, False, np.nan], dtype=np.dtype('O')), ...: 'd': pd.Series(['h', 'i', np.nan], dtype=np.dtype('O')), ...: 'e': pd.Series([10, np.nan, 20], dtype=np.dtype('float')), ...: 'f': pd.Series([np.nan, 100.5, 200], dtype=np.dtype('float')), ...: } ...: ) In [111]: df Out[111]: a b c d e f 0 1 x True h 10.0 NaN 1 2 y False i NaN 100.5 2 3 z NaN NaN 20.0 200.0 In [112]: df.dtypes Out[112]: a int32 b object c object d object e float64 f float64 dtype: object In [113]: dfn = df.convert_dtypes() In [114]: dfn Out[114]: a b c d e f 0 1 x True h 10 NaN 1 2 y False i <NA> 100.5 2 3 z <NA> <NA> 20 200.0 In [115]: dfn.dtypes Out[115]: a Int32 b string c boolean d string e Int64 f float64 dtype: objectEnd, that's all!refs: StackOverflow: Change column type in pandas 使用Pandas探索数据 http://niyanchun.com/explore-data-with-pandas.html 2018-05-17T01:01:00+08:00 做数据分析时,对数据越了解,越有助于我们去分析,本文介绍如何使用Pandas探索数据。1. Pandas简介Pandas是Python中一个高性能库,提供了非常易用的数据结构以及丰富的函数工具用来做数据分析,所以该库在数据分析领域用的非常广泛。使用Pandas的关键点在于理解Pandas的两个核心数据结构:Series和DataFrame。1.1 SeriesSeries表示带有标签的一维数组(one-dimensional labeled array):数组内的元素可以是任意类型;label称为index,index可以不唯一,但必须是可哈希的类型(hashable type)。构造Series结构最常用的方式就是使用pandas.Series类,参数及说明如下:pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)data:数组中的数据,参数可以是数组、字典或标量值index:标签或索引,可以重复,但必须是可哈希类型。参数可以是数组或一维的Index类型,长度必须和数据的长度相同;如果数据是字典类型,又显式的传了index,会覆盖字典的key;默认的index是(0, 1, 2, ..., len(data)-1)dtype:numpy.dtype或者None,如果传None的话,会自动检测类型。copy:布尔值,是否拷贝输入的值,默认是False。下面列举几个创建Series的例子。In [1]: import pandas as pd In [2]: import numpy as np # 使用数组创建Series,并指定index In [3]: arr = np.array([1,2,3,4,5]) In [4]: s = pd.Series(arr, index=['a','b','c','d','a']) In [5]: s Out[5]: a 1 b 2 c 3 d 4 a 5 dtype: int64 In [6]: s.index Out[6]: Index(['a', 'b', 'c', 'd', 'a'], dtype='object') # 使用数组创建Series,且使用默认的index In [7]: pd.Series(np.random.randn(5)) Out[7]: 0 -1.316523 1 -1.211854 2 -0.532214 3 -0.143331 4 0.335070 dtype: float64 # 通过字典创建Series In [8]: d = {'b':1, 'a':0, 'c':2} In [9]: pd.Series(d) Out[9]: a 0 b 1 c 2 dtype: int64 # 使用标量创建Series,要注意此时标量重复len(index)次 In [10]: pd.Series(5., index=['a','b','c','d','e']) Out[10]: a 5.0 b 5.0 c 5.0 d 5.0 e 5.0 dtype: float64在时间序列预测中Series数据结构将非常有用。1.2 DataFrameDataFrame和Series类似,但DataFrame是二维的,非常类似于关系型数据库里面的表。我们一般把列标签依旧称为index,而把行标签称为Column,对应的也有着两个参数去指定行列标签。DataFrame对象的构造方法和Series极其类似,参数情况如下:pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)这里不再赘述了,看以下一些例子:In [15]: d = { 'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']), ...: 'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])} ...: In [16]: d Out[16]: {'one': a 1.0 b 2.0 c 3.0 dtype: float64, 'two': a 1.0 b 2.0 c 3.0 d 4.0 dtype: float64} In [17]: df = pd.DataFrame(d) In [18]: df Out[18]: one two a 1.0 1.0 b 2.0 2.0 c 3.0 3.0 d NaN 4.0 In [19]: pd.DataFrame(d, index=['d', 'b', 'a']) Out[19]: one two d NaN 4.0 b 2.0 2.0 a 1.0 1.0 In [20]: pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three']) Out[20]: two three d 4.0 NaN b 2.0 NaN a 1.0 NaN In [21]: df.index Out[21]: Index(['a', 'b', 'c', 'd'], dtype='object') In [22]: df.columns Out[22]: Index(['one', 'two'], dtype='object')注:在Pandas中,缺失值一般用NaN表示。会创建Series和Pandas对象只是学习Pandas的第一步,其实Pandas更加强大的地方在于它在这两个核心数据结构之上提供了非常丰富的函数和方法,让我们可以更专注于数据分析本身。本文的重点不是介绍Pandas,所以Pandas的介绍到此为止,有兴趣的可以看起官方文档:http://pandas.pydata.org/pandas-docs/stable/index.html。里面有一个10分钟的入门教程,对于只想快速了解一下的同学是个非常不错的选择。下面我们言归正传,看一下如何利用Pandas提供的各种工具来探索我们的数据。2. 探索数据数据说明:本次示例所用的数据来自于https://archive.ics.uci.edu/ml/datasets/bank+marketing,是葡萄牙银行做的一次电话调查,旨在判断用户对于行方定期存储产品的认购情况。数据包含了很多列,有些列的值是标量型的,有些是数值型的。本文的重点在于如何利用Pandas工具去探索数据(分布)情况,所以列的含义不是那么重要,这里就不解释了,有兴趣的可以去上面给出的链接处查看,有详细的说明。导入相关的包并读入数据:In [1]: import numpy as np In [2]: import pandas as pd In [3]: import matplotlib.pyplot as plt In [4]: df = pd.read_csv('SampleData/banking.csv')2.1 统计信息1,查看数据基本信息。# head默认显示5条数据,可以指定显示几条 In [5]: df.head() Out[5]: age job marital education default housing loan \ 0 44 blue-collar married basic.4y unknown yes no 1 53 technician married unknown no no no 2 28 management single university.degree no yes no 3 39 services married high.school no no no 4 55 retired married basic.4y no yes no contact month day_of_week ... campaign pdays previous poutcome \ 0 cellular aug thu ... 1 999 0 nonexistent 1 cellular nov fri ... 1 999 0 nonexistent 2 cellular jun thu ... 3 6 2 success 3 cellular apr fri ... 2 999 0 nonexistent 4 cellular aug fri ... 1 3 1 success emp_var_rate cons_price_idx cons_conf_idx euribor3m nr_employed y 0 1.4 93.444 -36.1 4.963 5228.1 0 1 -0.1 93.200 -42.0 4.021 5195.8 0 2 -1.7 94.055 -39.8 0.729 4991.6 1 3 -1.8 93.075 -47.1 1.405 5099.1 0 4 -2.9 92.201 -31.4 0.869 5076.2 1 [5 rows x 21 columns] # 查看数据维度 In [6]: df.shape Out[6]: (41188, 21) # 查看数据类型 In [7]: df.dtypes Out[7]: age int64 job object marital object education object default object housing object loan object contact object month object day_of_week object duration int64 campaign int64 pdays int64 previous int64 poutcome object emp_var_rate float64 cons_price_idx float64 cons_conf_idx float64 euribor3m float64 nr_employed float64 y int64 dtype: object通过查看基本信息,我们可以查看到一些示例数据,以及数据总条数、维度数,各个维度的类型等,这些都是我们探索数据的第一步。2,通过Pandas的describe方法查看一些汇总信息,探索各个维度值的分布情况:In [11]: df.describe() Out[11]: age duration campaign pdays previous \ count 41188.00000 41188.000000 41188.000000 41188.000000 41188.000000 mean 40.02406 258.285010 2.567593 962.475454 0.172963 std 10.42125 259.279249 2.770014 186.910907 0.494901 min 17.00000 0.000000 1.000000 0.000000 0.000000 25% 32.00000 102.000000 1.000000 999.000000 0.000000 50% 38.00000 180.000000 2.000000 999.000000 0.000000 75% 47.00000 319.000000 3.000000 999.000000 0.000000 max 98.00000 4918.000000 56.000000 999.000000 7.000000 emp_var_rate cons_price_idx cons_conf_idx euribor3m \ count 41188.000000 41188.000000 41188.000000 41188.000000 mean 0.081886 93.575664 -40.502600 3.621291 std 1.570960 0.578840 4.628198 1.734447 min -3.400000 92.201000 -50.800000 0.634000 25% -1.800000 93.075000 -42.700000 1.344000 50% 1.100000 93.749000 -41.800000 4.857000 75% 1.400000 93.994000 -36.400000 4.961000 max 1.400000 94.767000 -26.900000 5.045000 nr_employed y count 41188.000000 41188.000000 mean 5167.035911 0.112654 std 72.251528 0.316173 min 4963.600000 0.000000 25% 5099.100000 0.000000 50% 5191.000000 0.000000 75% 5228.100000 0.000000 max 5228.100000 1.000000可以看到该方法默认只计算了数值型维度的5个方面的信息:count:总数mean:均值std:标准差min:最小值25%:第一四分位数或较小四分位数(Q1):等于该样本中所有数值由小到大排列后第25%的数字。50%:第二四分位数或中位数(Q2):等于该样本中所有数值由小到大排列后第50%的数字。75%:第三四分位数或较大四分位数(Q3):等于该样本中所有数值由小到大排列后第75%的数字。max:最大值。当然,对于数值型数据describe方法会统计上面5个方面的信息,对于标称型数据则统计另外4个方面的信息:In [13]: df.describe(exclude=[np.number]) Out[13]: job marital education default housing loan contact \ count 41188 41188 41188 41188 41188 41188 41188 unique 12 4 8 3 3 3 2 top admin. married university.degree no yes no cellular freq 10422 24928 12168 32588 21576 33950 26144 month day_of_week poutcome count 41188 41188 41188 unique 10 5 3 top may thu nonexistent freq 13769 8623 35563这4方面的信息包括:count:总数unique:去重后的个数top:出现频率最高的值freq:出现最高频率的值的频率对于Timestamp类型还会有first和last两个信息。3,通过groupby查看各个标称型维度值的分布情况。describe方法对于探索数值型数据的分布非常有用,但对于标称型数据虽然也有统计,但还不够。往往我们更多的使用groupby方法,该方法与SQL中的groupby类似,这里举几个例子:In [14]: df.groupby('education').size() Out[14]: education basic.4y 4176 basic.6y 2292 basic.9y 6045 high.school 9515 illiterate 18 professional.course 5243 university.degree 12168 unknown 1731 dtype: int64 In [15]: df.groupby('y').size() Out[15]: y 0 36548 1 4640 dtype: int644,有很多算法要求所选取的维度之间要没有相关性,所以探索维度之间的相关性也非常重要。Pandas提供了corr方法可以计算相关系数(默认计算皮尔逊相关系数):In [16]: df.corr() Out[16]: age duration campaign pdays previous \ age 1.000000 -0.000866 0.004594 -0.034369 0.024365 duration -0.000866 1.000000 -0.071699 -0.047577 0.020640 campaign 0.004594 -0.071699 1.000000 0.052584 -0.079141 pdays -0.034369 -0.047577 0.052584 1.000000 -0.587514 previous 0.024365 0.020640 -0.079141 -0.587514 1.000000 emp_var_rate -0.000371 -0.027968 0.150754 0.271004 -0.420489 cons_price_idx 0.000857 0.005312 0.127836 0.078889 -0.203130 cons_conf_idx 0.129372 -0.008173 -0.013733 -0.091342 -0.050936 euribor3m 0.010767 -0.032897 0.135133 0.296899 -0.454494 nr_employed -0.017725 -0.044703 0.144095 0.372605 -0.501333 y 0.030399 0.405274 -0.066357 -0.324914 0.230181 emp_var_rate cons_price_idx cons_conf_idx euribor3m \ age -0.000371 0.000857 0.129372 0.010767 duration -0.027968 0.005312 -0.008173 -0.032897 campaign 0.150754 0.127836 -0.013733 0.135133 pdays 0.271004 0.078889 -0.091342 0.296899 previous -0.420489 -0.203130 -0.050936 -0.454494 emp_var_rate 1.000000 0.775334 0.196041 0.972245 cons_price_idx 0.775334 1.000000 0.058986 0.688230 cons_conf_idx 0.196041 0.058986 1.000000 0.277686 euribor3m 0.972245 0.688230 0.277686 1.000000 nr_employed 0.906970 0.522034 0.100513 0.945154 y -0.298334 -0.136211 0.054878 -0.307771 nr_employed y age -0.017725 0.030399 duration -0.044703 0.405274 campaign 0.144095 -0.066357 pdays 0.372605 -0.324914 previous -0.501333 0.230181 emp_var_rate 0.906970 -0.298334 cons_price_idx 0.522034 -0.136211 cons_conf_idx 0.100513 0.054878 euribor3m 0.945154 -0.307771 nr_employed 1.000000 -0.354678 y -0.354678 1.000000皮尔逊相关系数取值范围为[-1, 1],-1表示(线性)负相关,0表示(线性)无关,1表示(线性)正相关。通过这个(对角)矩阵,我们可以很容易的看出各个属性间的相关性。5,pandas还提供了skew来计算偏度(skew):衡量实数随机变量概率分布的不对称性。偏度的值可以为正,可以为负或者甚至是无法定义。在数量上,偏度为负(左偏态或负偏态,Negative Skew)就意味着在概率密度函数左侧的尾部比右侧的长,绝大多数的值(包括中位数在内)位于平均值的右侧。偏度为正(右偏态或正偏态,Positive Skew)就意味着在概率密度函数右侧的尾部比左侧的长,绝大多数的值(但不一定包括中位数)位于平均值的左侧。如图:偏度为零就表示数值相对均匀地分布在平均值的两侧,但不一定意味着其为对称分布。如果分布对称,那么平均值=中位数,偏度为零(此外,如果分布为单峰分布,那么平均值=中位数=众数)。In [17]: df.skew() Out[17]: age 0.784697 duration 3.263141 campaign 4.762507 pdays -4.922190 previous 3.832042 emp_var_rate -0.724096 cons_price_idx -0.230888 cons_conf_idx 0.303180 euribor3m -0.709188 nr_employed -1.044262 y 2.450330 dtype: float642.2 可视化统计信息虽然非常精确,但看上去并不是非常直观,我们可以通过一些可视化的手段来非常直观的探索数据分布。1,直方图(histogram):In [20]: %matplotlib Using matplotlib backend: MacOSX In [21]: df.hist(figsize=(12, 8))2,密度图(density plot):In [22]: df.plot(kind='density', subplots=True, figsize=(12,8), layout=(3,4), sharex=False)3,箱型图(boxplots):In [23]: df.plot(kind='box', subplots=True, figsize=(12,8), layout=(3,4), sharex=False, sharey=False)箱型图的含义参见:箱型图介绍。4,相关系数矩阵图:corr = df.corr() figure = plt.figure(figsize=(12,8)) ax = figure.add_subplot(111) cax = ax.matshow(corr, vmin=-1, vmax=1) figure.colorbar(cax) plt.show() # 0~10,依次对应age~y5,通过散点矩阵图(scatter matrix)查看各维度相关性:from pandas.plotting import scatter_matrix scatter_matrix(df, figsize=(18, 12))关于scatter matrix需要解释一下,和上面的相关系数矩阵图类似,该图也描述了各维度间的相关性。而对角线上是各个维度自己与自己的相关性,显然都是完全相关的,也就是一条直线(皮尔逊相关系数为1),这没什么用。所以Pandas就把对角线上面的改为展示维度的密度图了。这里再附上皮尔逊相关系数的值与其图形的关系(图片来自皮尔逊相关系数维基百科):以及一个比较泛(不是非常的严格和通用)的判断相关性强弱的标准:相关性负正无-0.09~0.00.0~0.09弱-0.3~-0.10.1~0.3中-0.5~-0.30.3~0.5强-1.0~-0.50.5~1.0可视化可以帮助我们“定性的”了解数据,统计信息则帮助我们“定量的”了解数据,二者结合可以使我们更加了解自己的数据,从而选择下一步的数据处理流程。除了本文已经介绍的之外,Pandas还有非常非常多的工具帮助我们分析数据,可以查看其文档慢慢积累。本文源码见这里。References:维基百科(具体各个链接见博客内容)。Pandas官方文档.Machine Learning Mastery with Python.