前言 开刷Pandas数据分析,看起来很好理解,不过没做笔记没敲代码心里总是不安稳,所以复现下课程代码并演示其中遇到的问题,顺便水一水笔记好了
参考资料:
课程视频链接:Pandas数据分析从入门到实战 
数据及代码示例:ant-learn-pandas: pandas学习课程代码仓库 (gitee.com) 
一、数据读取 0. 数据类型 
数据类型 
说明 
Pandas读取方法 
 
 
csv, tsv, txt 
用逗号、tab或其它字符分割的文本文件 
read_csv 
 
excel 
xls或xlsx文件 
read_excel 
 
mysql 
关系型数据表 
read_sql 
 
 
 
1. read_csv 1.1 读取csv文件 csv是以逗号分割的文本文件,如下:
1 2 3 4 5 userId,movieId,rating,timestamp 1,1,4.0,964982703 1,3,4.0,964981247 1,6,4.0,964982224 1,47,5.0,964983815 
 
直接使用read_csv读取该文件
1 2 3 fpath = "../datas/ml-latest-small/ratings.csv"  ratings = pd.read_csv(fpath) 
 
1.2 指定分割符 已知access_pvuv.txt如下:1 2 3 4 5 6 7 8 9 10 2019-09-10  139    92 2019-09-09  185    153 2019-09-08  123    59 2019-09-07  65     40 2019-09-06  157    98 2019-09-05  205    151 2019-09-04  196    167 2019-09-03  216    176 2019-09-02  227    148 2019-09-01  105    61 
为read_csv添加参数delimiter (或seq)  指定分隔符,header=None 表示没有第一行列名称1 2 3 4 5 6 7 8 fpath = "../datas/crazyant/access_pvuv.txt"  pvuv = pd.read_csv(     fpath,     delimiter='\t' ,     header=None ,     names=['date' , 'pv' , 'uv' ] ) 
分割符也可以是多个字符,但是seq指定多个字符默认会被当作正则表达式,需指定engine=’python’
1 2 3 4 5 6 7 df_ratings = pd.read_csv(     "../datas/movielens-1m/ratings.dat" ,     sep="::" ,     engine='python' ,     names="UserID::MovieID::Rating::Timestamp" .split("::" ) ) 
 
2. read_excel 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 fpath = "../datas/crazyant/access_pvuv.xlsx"  pvuv = pd.read_excel(fpath) print (pvuv)''' 输出结果            日期   PV   UV 0  2019-09-10  139   92 1  2019-09-09  185  153 2  2019-09-08  123   59 3  2019-09-07   65   40 4  2019-09-06  157   98 5  2019-09-05  205  151 6  2019-09-04  196  167 7  2019-09-03  216  176 8  2019-09-02  227  148 9  2019-09-01  105   61 ''' 
 
3. read_sql 3.1 使用pymysql 连接数据库,选择编码方式
1 2 3 4 5 6 7 8 9 10 import  pandas as  pdimport  pymysqlconn = pymysql.connect(     host='localhost' ,     user='root' ,     password='password' ,     database='dbname' ,     charset='utf8'  ) 
 
1 2 3 4 5 6 7 8 9 table = pd.read_sql("select * from tbname" , con=conn) print (table)''' 输出结果    id                       preorder_traversal_string 0   1             4_2_1_0_#_#_#_3_#_#_8_7_#_#_11_#_#_ 1   2  5_4_2_#_#_1_7_#_6_#_#_#_3_0_#_5_1_#_#_#_6_#_#_ 2   3                  6_#_7_5_3_#_#_1_#_#_2_8_#_#_#_ ''' 
 
但是会报警告:
 UserWarning: pandas only supports SQLAlchemy connectable (engine/connection) or database string URI or sqlite3 DBAPI2 connection. Other DBAPI2 objects are not tested. Please consider using SQLAlchemy.
 
这里建议我们使用SQLAlchemy
3.2 使用SQLAlchemy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import  pandas as  pdfrom  sqlalchemy import  create_enginehost = "127.0.0.1"  user = "root"  password = "password"  database = "dbname"  engine = create_engine(f"mysql+pymysql://{user} :{password} @{host} /{database} " ) sql = 'select * from tbname'  table = pd.read_sql(sql=sql, con=engine) print (table)''' 输出结果    id                       preorder_traversal_string 0   1             4_2_1_0_#_#_#_3_#_#_8_7_#_#_11_#_#_ 1   2  5_4_2_#_#_1_7_#_6_#_#_#_3_0_#_5_1_#_#_#_6_#_#_ 2   3                  6_#_7_5_3_#_#_1_#_#_2_8_#_#_#_ ''' 
 
4. 查看数据格式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 print (ratings.head())''' 输出结果    userId  movieId  rating  timestamp 0       1        1     4.0  964982703 1       1        3     4.0  964981247 2       1        6     4.0  964982224 3       1       47     5.0  964983815 4       1       50     5.0  964982931 ''' print (ratings.shape)''' 输出结果 (100836, 4) ''' print (ratings.columns)''' 输出结果 Index(['userId', 'movieId', 'rating', 'timestamp'], dtype='object') ''' print (ratings.index)''' 输出结果 RangeIndex(start=0, stop=100836, step=1) ''' print (ratings.dtypes)''' 输出结果 userId         int64 movieId        int64 rating       float64 timestamp      int64 dtype: object ''' 
 
二、数据结构 1. Series 1 2 3 4 5 6 7 8 9 10 11 12 import  pandas as  pds1 = pd.Series(list ('abcd' )) print (s1)''' 0    a 1    b 2    c 3    d dtype: object ''' 
 
1 2 3 4 5 6 7 8 9 10 11 12 s2 = pd.Series(list ('efgh' ), index=list ('abcd' )) print (s2)print (s2.index)''' a    e b    f c    g d    h dtype: object Index(['a', 'b', 'c', 'd'], dtype='object') ''' 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 dict  = {    'a' : 'e' ,     'b' : 'f' ,     'c' : 'g' ,     'd' : 'h'  } s3 = pd.Series(dict ) print (s3)''' a    e b    f c    g d    h dtype: object ''' 
 
2. DataFrame 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import  pandas as  pddata = {         'state' : ['Ohio' , 'Ohio' , 'Ohio' , 'Nevada' , 'Nevada' ],         'year' : [2000 , 2001 , 2002 , 2001 , 2002 ],         'pop' : [1.5 , 1.7 , 3.6 , 2.4 , 2.9 ]     } df = pd.DataFrame(data) print (df)'''     state  year  pop 0    Ohio  2000  1.5 1    Ohio  2001  1.7 2    Ohio  2002  3.6 3  Nevada  2001  2.4 4  Nevada  2002  2.9 ''' 
 
1 2 3 4 5 6 7 8 9 10 11 12 print (df.index, '\n\n' , df.columns, '\n\n' , df.dtypes)''' RangeIndex(start=0, stop=5, step=1)  Index(['state', 'year', 'pop'], dtype='object')  state     object year       int64 pop      float64 dtype: object ''' 
 
三、查询数据 0. 查询方法 
df.loc :基于标签索引,结果包含最后一个标签的值 
df.iloc:基于位置索引,结果不包含最后一个位置的值 
df.where 
df.query 
 
本节主要介绍df.loc
1. 数据预处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import  pandas as  pddf = pd.read_csv("../datas/beijing_tianqi/beijing_tianqi_2018.csv" ) print (df.head())'''           ymd bWendu yWendu tianqi fengxiang fengli  aqi aqiInfo  aqiLevel 0  2018-01-01     3℃    -6℃   晴~多云       东北风   1-2级   59       良         2 1  2018-01-02     2℃    -5℃   阴~多云       东北风   1-2级   49       优         1 2  2018-01-03     2℃    -5℃     多云        北风   1-2级   28       优         1 3  2018-01-04     0℃    -8℃      阴       东北风   1-2级   28       优         1 4  2018-01-05     3℃    -6℃   多云~晴       西北风   1-2级   50       优    ''' 
 
1 2 df.set_index('ymd' , inplace=True ) 
 
1 2 3 4 5 df.loc[:, "bWendu" ] = df["bWendu" ].str .replace("℃" , "" ).astype('int32' ) df.loc[:, "yWendu" ] = df["yWendu" ].str .replace("℃" , "" ).astype('int32' ) 
 
1 2 3 4 5 6 7 8 9 10 print (df.head())'''             bWendu  yWendu tianqi fengxiang fengli  aqi aqiInfo  aqiLevel ymd 2018-01-01       3      -6   晴~多云       东北风   1-2级   59       良         2 2018-01-02       2      -5   阴~多云       东北风   1-2级   49       优         1 2018-01-03       2      -5     多云        北风   1-2级   28       优         1 2018-01-04       0      -8      阴       东北风   1-2级   28       优         1 2018-01-05       3      -6   多云~晴       西北风   1-2级   50       优     ''' 
 
这里会报一个警告:1 2 3 DeprecationWarning: In  a  future  version , `df.iloc [:, i ] = newvals ` will  attempt  to  set  the   values  inplace  instead  of  always  setting  a  new  array . To  retain  the  old  behavior , use  either `df [df.columns [i ]] = newvals ` or , if  columns  are  non -unique , `df.isetitem (i , newvals )` 
2. 按数值、列表、区间查询 1 2 single_value = df.loc['2018-01-03' , 'bWendu' ] 
 
1 2 3 s1 = df.loc['2018-01-03' , ['bWendu' , 'yWendu' ]] s2 = df.loc[['2018-01-03' , '2018-01-04' , '2018-01-05' ], 'bWendu' ] 
 
1 2 df2 = df.loc[['2018-01-03' ,'2018-01-04' ,'2018-01-05' ], ['bWendu' , 'yWendu' ]] 
 
1 2 df3 = df.loc['2018-01-03' :'2018-01-05' , 'bWendu' :'fengxiang' ] 
 
3. 条件查询 1 2 3 4 5 6 7 8 9 10 df4 = df.loc[(df["bWendu" ] <= 30 ) & (df["yWendu" ] >= 15 )         & (df["tianqi" ] == '晴' ) & (df["aqiLevel" ] == 1 ), :] print (df4)'''             bWendu  yWendu tianqi fengxiang fengli  aqi aqiInfo  aqiLevel ymd 2018-08-24      30      20      晴        北风   1-2级   40       优         1 2018-09-07      27      16      晴       西北风   3-4级   22       优         1 ''' 
 
其中,条件表达式返回的是一个布尔值的Series
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 print (df["yWendu" ] < -10 )''' 2018-01-01    False 2018-01-02    False 2018-01-03    False 2018-01-04    False 2018-01-05    False               ... 2018-12-27     True 2018-12-28     True 2018-12-29     True 2018-12-30     True 2018-12-31    False Name: yWendu, Length: 365, dtype: bool ''' 
 
4. 函数查询 1 2 df5 = df.loc[lambda  df : (df["bWendu" ] <= 30 ) & (df["yWendu" ] >= 15 ), :] 
 
1 2 3 4 5 def  query_my_data (df ):    return  df.index.str .startswith("2018-09" ) & (df["aqiLevel" ] == 1 ) df6 = df.loc[query_my_data, :] 
 
四、新增数据列 1. 直接赋值 1 df.loc[:, 'wencha' ] = df['bWendu' ] - df['yWendu' ] 
 
2. df.apply 传入一个函数并选定axis:
当axis=1,函数的参数为一行的Series(常用) 
当axis=0,函数的参数为一列的Series 
 
1 2 3 4 5 6 7 8 def  get_wendu_type (x ):    if  x["bWendu" ] > 33 :         return  '高温'      if  x["yWendu" ] < -10 :         return  '低温'      return  '常温'  df.loc[:, "wendu_type" ] = df.apply(get_wendu_type, axis=1 ) 
 
3. df.assign df.assign总是会创建一个新的copy 
利用lambda表达式,处理原来的数据得到新列
1 2 3 4 5 6 # 可以同时添加多个新的列 df.assign(     yWendu_huashi = lambda x : x["yWendu"] * 9 / 5 + 32,     # 摄氏度转华氏度     bWendu_huashi = lambda x : x["bWendu"] * 9 / 5 + 32 ) 
 
4. Series.map 传入一个字典,将Series的值根据字典映射
示例如下:
原始数据
1 2 3 stocks = pd.read_excel('../datas/stocks/互联网公司股票.xlsx' ) print (stocks.head(), '\n' , stocks['公司' ].unique())
 
1 2 3 4 5 6 7            日期    公司      收盘      开盘       高       低    交易量   涨跌幅 0   2019 -10 -03   BIDU  104 .32   102 .35   104 .73   101 .15    2 .24   0 .02 1   2019 -10 -02   BIDU  102 .62   100 .85   103 .24    99 .50    2 .69   0 .01 2   2019 -10 -01   BIDU  102 .00   102 .80   103 .26   101 .00    1 .78  -0 .01 3   2019 -10 -03   BABA  169 .48   166 .65   170 .18   165 .00   10 .39   0 .02 4   2019 -10 -02   BABA  165 .77   162 .82   166 .88   161 .90   11 .60   0 .00  ['BIDU' 'BABA' 'IQ' 'JD'] 
 
现将 公司 这一列通过字典对应到该公司的中文名
1 2 3 4 5 6 7 8 9 10 dict_company_names = {     "bidu" : "百度" ,     "baba" : "阿里巴巴" ,     "iq" : "爱奇艺" ,     "jd" : "京东"  } stocks['公司中文' ] = stocks['公司' ].str .lower().map (dict_company_names) print (stocks['公司中文' ].unique())
 
1 ['百度' '阿里巴巴' '爱奇艺' '京东'] 
 
其实map也可以像apply一样传一个函数,修改Series的每个值
5. 条件选择分组后赋值  
错误示例: 
1 2 3 df.loc[df["bWendu" ]-df["yWendu" ]>10 ]["wencha_type" ] = "温差大"  df.loc[df["bWendu" ]-df["yWendu" ]<=10 ]["wencha_type" ] = "温差正常"  
 
两个[]的链式操作相当于1 df.get(condition).set (wen_cha) 
 这里get得到的结果可能是view也可能是copy,存在歧义
正确示范: 
1 2 3 df.loc[df["bWendu" ]-df["yWendu" ]>10 , "wencha_type" ] = "温差大"  df.loc[df["bWendu" ]-df["yWendu" ]<=10 , "wencha_type" ] = "温差正常"  
 
五、聚合查询 1. describe输出统计结果  
1 2 3 4 5 6 7 8 9            bWendu      yWendu         aqi    aqiLevel      wencha count  365 .000000   365 .000000   365 .000000   365 .000000   365 .000000  mean    18 .665753     8 .358904    82 .183562     2 .090411    10 .306849  std     11 .858046    11 .755053    51 .936159     1 .029798     2 .781233  min     -5 .000000   -12 .000000    21 .000000     1 .000000     2 .000000  25 %      8 .000000    -3 .000000    46 .000000     1 .000000     8 .000000 50 %     21 .000000     8 .000000    69 .000000     2 .000000    10 .000000 75 %     29 .000000    19 .000000   104 .000000     3 .000000    12 .000000 max     38 .000000    27 .000000   387 .000000     6 .000000    18 .000000  
 
describe只能得到数值列的统计结果
2. 非数值列统计 2.1 unique唯一去重 1 print (df['tianqi' ].unique())
 
1 2 3 4 ['晴~多云' '阴~多云' '多云' '阴' '多云~晴' '多云~阴' '晴' '阴~小雪' '小雪~多云' '小雨~ 阴' '小雨~雨夹雪'  '多云~小雨' '小雨~多云' '大雨~小雨' '小雨' '阴~小雨' '多云~雷阵雨' '雷阵雨~多云' '阴~ 雷阵雨' '雷阵雨'  '雷阵雨~大雨' '中雨~雷阵雨' '小雨~大雨' '暴雨~雷阵雨' '雷阵雨~中雨' '小雨~雷阵雨' '雷 阵雨~阴' '中雨~小雨'  '小雨~中雨' '雾~多云' '霾'] 
 
2.2 value_counts按值计数 1 print (df['wencha_type' ].value_counts())
 
1 2 3 温差正常    187  温差大     178  Name: wencha_type , dtype : int64  
 
3. 协方差和相关系数 1 print (df.cov(), '\n\n' , df.corr())
 
1 2 3 4 5 6 7 8 9 10 11 12 13               bWendu      yWendu          aqi   aqiLevel     wencha bWendu    140 .613247   135 .529633     47 .462622    0 .879204    5 .083614  yWendu    135 .529633   138 .181274     16 .186685    0 .264165   -2 .651641  aqi        47 .462622    16 .186685   2697 .364564   50 .749842   31 .275937  aqiLevel    0 .879204     0 .264165     50 .749842    1 .060485    0 .615038  wencha      5 .083614    -2 .651641     31 .275937    0 .615038    7 .735255               bWendu    yWendu       aqi  aqiLevel    wencha bWendu    1 .000000   0 .972292   0 .077067   0 .071999   0 .154142  yWendu    0 .972292   1 .000000   0 .026513   0 .021822  -0 .081106  aqi       0 .077067   0 .026513   1 .000000   0 .948883   0 .216523  aqiLevel  0 .071999   0 .021822   0 .948883   1 .000000   0 .214740  wencha    0 .154142  -0 .081106   0 .216523   0 .214740   1 .000000  
 
4. 分组后聚合查询 4.1 pd.groupby DataFrame.groupby(by, axis=0, as_index=True, sort=True, group_keys=True,  dropna=True) 
by: 字符串或者List<字符串>,用于指定分组 
axis:默认为0,对行做分组 
as_index:将分组的keys作为索引值,默认为True 
sort:将结果按分组的keys排序,默认为True 
group_keys:与as_index相同,但是只有在使用apply时生效,在使用聚合时失效(都为True) 
 
DataFrame.groupby的返回值是一个DataFrameGroupBy对象
4.2 聚合查询示例 1) 使用已有的聚合函数 
1 2 3 4 df = pd.DataFrame({'A' : ['foo' , 'bar' , 'foo' , 'bar' , 'foo' , 'bar' , 'foo' , 'foo' ],                    'B' : ['one' , 'one' , 'two' , 'three' , 'two' , 'two' , 'one' , 'three' ],                    'C' : np.random.randn(8 ),                    'D' : np.random.randn(8 )}) 
 
1 2 3 4 5 6      A      B         C         D 0   foo    one  0 .411257  -1 .345015 1   bar    one  0 .680037   0 .225904 2   foo    two -0 .640561  -0 .447943 3   bar  three -0 .354500  -0 .517335 4   foo    two  1 .092376  -0 .978323 
 
agg列表传参,对不同列使用相同聚合函数:1 df_group1 = df.groupby(['A' , 'B' ]).agg([np.sum , np.mean]) 
1 2 3 4 5 6 7 8 9                   C                   D                 sum      mean       sum      mean A   B bar one    0 .680037   0 .680037   0 .225904   0 .225904      three -0 .354500  -0 .354500  -0 .517335  -0 .517335      two   -1 .047294  -1 .047294  -1 .879435  -1 .879435  foo one    0 .419079   0 .209540  -1 .893515  -0 .946758      three -0 .681836  -0 .681836   1 .008956   1 .008956      two    0 .451816   0 .225908  -1 .426266  -0 .713133  
 agg对象传参,对不同列使用不同聚合函数:1 df_group2 = df.groupby(['A' , 'B' ]).agg({'C' : np.sum , 'D' : np.mean}) 
1 2 3 4 5 6 7 8                    C         D A   B bar one    0 .680037   0 .225904      three -0 .354500  -0 .517335      two   -1 .047294  -1 .879435  foo one    0 .419079  -0 .946758      three -0 .681836   1 .008956      two    0 .451816  -0 .713133  
DataFrameGroupBy对象原生的函数:1 df_group3 = df.groupby('A' )['C' ].mean() 
1 2 3 4 A bar   -0 .240586  foo    0 .037812  Name: C , dtype : float64  
2)自定义聚合函数 
DataFrameGroupBy.apply(func,  args,  \ *kwargs)
func:自定义的聚合函数,第一个参数是一个DataFrame 
args, \ *kwargs:func第二个及往后的参数(如有) 
 
使用的数据为多次出现在例子中的天气数据,增加一列为月份,由ymd年月日得到:1 2 df['month' ] = df['ymd' ].str [:7 ] 
1 2 3 4 5 6           ymd  bWendu  yWendu tianqi  ... aqi aqiInfo  aqiLevel    month 0   2018 -01 -01        3       -6    晴~多云  ...  59        良         2   2018 -01 1   2018 -01 -02        2       -5    阴~多云  ...  49        优         1   2018 -01 2   2018 -01 -03        2       -5      多云  ...  28        优         1   2018 -01 3   2018 -01 -04        0       -8       阴  ...  28        优         1   2018 -01 4   2018 -01 -05        3       -6    多云~晴  ...  50        优         1   2018 -01 
对月份做分组,并对分组后的数据对最高温度做排序,返回最高温度最大的3行
1 2 3 4 def  getTopN (df, n ):    return  df.sort_values(by='bWendu' )[['ymd' , 'bWendu' , 'yWendu' ]][-n:] df_group = df.groupby('month' ).apply(getTopN, 3 ) 
 
1 2 3 4 5 6 7                    ymd  bWendu  yWendu month 2018 -01  16   2018 -01 -17        6       -7         13   2018 -01 -14        6       -5          18   2018 -01 -19        7       -4  2018 -02  58   2018 -02 -28        9       -2         53   2018 -02 -23       10       -4  
 
六、缺失值处理 1. 处理方式 Pandas使用这些函数处理缺失值:
isnull和notnull:检测是否是空值,可用于df和series 
dropna:丢弃、删除缺失值
axis : 删除行还是列,{0 or ‘index’, 1 or ‘columns’}, default 0 
how : 如果等于any则任何值为空都删除,如果等于all则所有值都为空才删除 
inplace : 如果为True则修改当前df,否则返回新的df 
 
 
fillna:填充空值
value:用于填充的值,可以是单个值,或者字典(key是列名,value是值) 
method : 等于ffill使用前一个不为空的值填充forword fill;等于bfill使用后一个不为空的值填充backword fill 
axis : 按行还是列填充,{0 or ‘index’, 1 or ‘columns’} 
inplace : 如果为True则修改当前df,否则返回新的df 
 
 
 
2. 数据清洗示例 
2.1 检测空值 1 2 3 4 5 studf = pd.read_excel("../datas/student_excel/student_excel.xlsx" , skiprows=2 ) print (studf.isnull())
 
1 2 3 4 5 6 7 8 9 10 11 12     Unnamed: 0     姓名     科目     分数 0         True   False   False   False  1         True    True   False   False  2         True    True   False   False  3         True    True    True    True  4         True   False   False   False  5         True    True   False    True  6         True    True   False   False  7         True    True    True    True  8         True   False   False   False  9         True    True   False   False  10        True    True   False   False  
 
2.2 dropna示例 1 2 3 4 5 studf.dropna(axis=1 , how='all' , inplace=True ) studf.dropna(axis=0 , how='all' , inplace=True ) print (studf)
 
1 2 3 4 5 6 7 8 9 10      姓名  科目    分数 0     小明  语文  85 .0 1    NaN  数学  80 .0 2    NaN  英语  90 .0 4     小王  语文  85 .0 5    NaN  数学   NaN6    NaN  英语  90 .0 8     小刚  语文  85 .0 9    NaN  数学  80 .0 10   NaN  英语  90 .0 
 
2.3 fillna示例 1 2 3 4 5 6 studf['分数' ].fillna(value=0 , inplace=True ) studf['姓名' ].fillna(method='ffill' , inplace=True ) print (studf)
 
1 2 3 4 5 6 7 8 9 10     姓名  科目    分数 0    小明  语文  85 .0 1    小明  数学  80 .0 2    小明  英语  90 .0 4    小王  语文  85 .0 5    小王  数学   0 .0 6    小王  英语  90 .0 8    小刚  语文  85 .0 9    小刚  数学  80 .0 10   小刚  英语  90 .0 
 
七、数据排序 1. 排序方法 1) Series的排序:    Series.sort_values(ascending=True, inplace=False)     参数说明:
ascending:默认为True升序排序,为False降序排序 
inplace:是否修改原始Series 
 
2) DataFrame的排序:    DataFrame.sort_values(by, ascending=True, inplace=False)     参数说明:
by:字符串或者List<字符串>,单列排序或者多列排序 
ascending:bool或者bool的列表,升序还是降序,如果是list对应by的多列 
inplace:是否修改原始DataFrame 
 
2. 排序示例 1 2 print (df['aqi' ].sort_values())
 
1 2 3 4 5 6 7 8 9 10 11 12 13 ymd 2018 -09 -29      21 2018 -10 -09      21 2018 -09 -07      22 2018 -09 -30      22 2018 -10 -29      22              ... 2018 -11 -14     266 2018 -03 -13     287 2018 -04 -02     287 2018 -03 -14     293 2018 -03 -28     387 Name: aqi , Length : 365, dtype : int64  
 
1 2 3 df.sort_values(by=['aqi' , 'bWendu' ], ascending=[False , True ], inplace=True ) print (df[['aqi' , 'bWendu' ]])
 
1 2 3 4 5 6 7 8 9 10 11 12 13             aqi  bWendu ymd 2018 -03 -28   387       25 2018 -03 -14   293       15 2018 -03 -13   287       17 2018 -04 -02   287       26 2018 -11 -14   266       13 ...         ...     ... 2018 -10 -29    22       15 2018 -09 -30    22       19 2018 -09 -07    22       27 2018 -10 -09    21       15 2018 -09 -29    21       22 
 
八、字符串处理 0. Pandas的str Pandas的字符串处理: 
使用方法:先获取Series的str属性,然后在属性上调用函数; 
只能在字符串列上使用,不能数字列上使用; 
Dataframe上没有str属性和处理方法 
Series.str并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似; 
 
1. 基础用法 获取str属性,并调用各种方法,如replace, isnumeric, len
1 print (df['wencha_type' ].str .len ())
 
1 2 3 4 5 6 7 8 9 10 11 12 13 ymd 2018 -03 -28     3 2018 -03 -14     4 2018 -03 -13     3 2018 -04 -02     3 2018 -11 -14     4              .. 2018 -10 -29     3 2018 -09 -30     4 2018 -09 -07     3 2018 -10 -09     3 2018 -09 -29     3 Name: wencha_type , Length : 365, dtype : int64  
 
2. 条件查询 或使用contains, startswith等得到bool的Series做条件查询
1 print (df.loc[df['tianqi' ].str .startswith('多云' ), ['tianqi' , 'fengxiang' ]])
 
1 2 3 4 5 6 7 8 9 10 11 12 13            tianqi fengxiang ymd 2018 -03 -28    多云~晴        东风2018 -03 -14    多云~阴       东北风2018 -04 -02      多云        北风2018 -11 -14      多云        南风2018 -11 -26      多云       东南风...           ...       ... 2018 -01 -25      多云       东北风2018 -10 -10    多云~晴       西北风2018 -02 -03      多云        北风2018 -09 -30      多云       西北风2018 -10 -09    多云~晴       西北风
 
3. 正则表达式 由于Series.str天然支持正则表达式,示例如下:
匹配字符集合并做替换:
1 2 3 4 5 6 7 8 9 def  get_nianyueri (x ):    year,month,day = x["ymd" ].split("-" )     return  f"{year} 年{month} 月{day} 日"  df["中文日期" ] = df.apply(get_nianyueri, axis=1 ) df.loc[:, '中文日期' ] = df['中文日期' ].str .replace('[年月日]' , '' ) print (df['中文日期' ])
 
1 2 3 4 5 6 7 8 9 10 11 12 86      20180328 72      20180314 71      20180313 91      20180402 317     20181114          ... 301     20181029 272     20180930 249     20180907 281     20181009 271     20180929 Name: 中文日期, Length : 365, dtype : object  
 
捕获组提取数据:1 2 extracted_fengli = df['fengli' ].str .extract(r'(\d)-(\d)' ) print (extracted_fengli.head())
1 2 3 4 5 6 7 8 9 10 11 12      0   1  86    1   2 72    1   2 71    1   2 91    1   2 317   1   2 ..  .. .. 301   3   4 272   4   5 249   3   4 281   4   5 271   3   4 
 
九、索引 0. 索引的作用 选择恰当的索引可以加速查询性能
当索引是唯一 的时,Pandas会用哈希表优化性能,时间复杂度为O(1) 
当索引不唯一,但是单调 时,Pandas会使用二分查找,时间复杂度为O(log n) 
当索引既不唯一且不单调时,Pandas只能遍历,时间复杂度为O(n) 
 
因此,我们要判断当前索引是否为以上类型,尽可能选择唯一的索引,单调次之
1. 选择索引示例 原始数据如下:
 
1 2 3 4 5 6    userId  movieId  rating  timestamp 0        1         1      4 .0   964982703 1        1         3      4 .0   964981247 2        1         6      4 .0   964982224 3        1        47      5 .0   964983815 4        1        50      5 .0   964982931 
 
判断每一列是否存在唯一约束:
1 print (df.nunique() == len (df))
 
1 2 3 4 5 userId       False movieId      False rating       False timestamp    False dtype: bool  
 
判断每一列是否单调:
1 2 3 4 5 6 7 is_monotonic_increasing = df.apply(lambda  x: x.is_monotonic_increasing) is_monotonic_decreasing = df.apply(lambda  x: x.is_monotonic_decreasing) print (is_monotonic_increasing, '\n\n' , is_monotonic_decreasing)
 
1 2 3 4 5 6 7 8 9 10 11 userId        True movieId      False rating       False timestamp    False dtype: bool   userId        False  movieId       False rating        False timestamp     False dtype : bool 
 
2. 设置索引示例 DataFrame.set_index(keys, append=False, drop=True, inplace=False) 
keys代表被用作索引的列
append代表是否保留原来的索引
drop表示是否将指定的列在原数据列中删除
inplace表示是否在原数据上修改
1 2 df.set_index('userId' ,append=True , drop=False , inplace=True ) print (df.head())
 
1 2 3 4 5 6 7           userId  movieId  rating  timestamp   userId 0  1             1         1      4 .0   964982703 1  1             1         3      4 .0   964981247 2  1             1         6      4 .0   964982224 3  1             1        47      5 .0   964983815 4  1             1        50      5 .0   964982931 
 
十、数据合并 1. merge合并 1.1 函数定义 课件中给出的pd.merge 的解释如下:
pd.merge(left, right, how=‘inner’, on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True, suffixes=(‘_x’, ‘_y’), copy=True, indicator=False, validate=None) 
left,right:要merge的dataframe或者有name的Series 
how:join类型,‘left’, ‘right’, ‘outer’, ‘inner’ 
on:join的key,left和right都需要有这个key 
left_on:left的df或者series的key 
right_on:right的df或者seires的key 
left_index,right_index:使用index而不是普通的column做join 
suffixes:两个元素的后缀,如果列有重名,自动添加后缀,默认是(‘_x’, ‘_y’) 
 
如果学过SQL语句,可以很好地将两者对应起来:
pd.merge(left, right, on=’key’) 相当于 FROM left JOIN  right ON left.key=right.key
pd.merge(left, right, left_on=’key1’, right_on=’key2’) 相当于 FROM left JOIN  right ON left.key1=right.key2
而how=’left’/‘right’/‘outer’就相当于LEFT/RIGHT/FULL JOIN
1.2 合并示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 df_ratings = pd.read_csv(     "../datas/movielens-1m/ratings.dat" ,     sep="::" ,     engine='python' ,     names="UserID::MovieID::Rating::Timestamp" .split("::" ) ) df_users = pd.read_csv(     "../datas/movielens-1m/users.dat" ,     sep="::" ,     engine='python' ,     names="UserID::Gender::Age::Occupation::Zip-code" .split("::" ) ) print (df_ratings.head(), '\n' , df_users.head())df_joined1 = pd.merge(df_ratings, df_users, on='UserID' ) print (df_joined1.head())
 
输出结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18    UserID  MovieID  Rating  Timestamp 0        1      1193        5   978300760 1        1       661        3   978302109 2        1       914        3   978301968 3        1      3408        4   978300275 4        1      2355        5   978824291     UserID Gender  Age  Occupation Zip-code 0        1       F    1           10     48067 1        2       M   56           16     70072 2        3       M   25           15     55117 3        4       M   45            7     02460 4        5       M   25           20     55455    UserID  MovieID  Rating  Timestamp Gender  Age  Occupation Zip-code 0        1      1193        5   978300760       F    1           10     48067 1        1       661        3   978302109       F    1           10     48067 2        1       914        3   978301968       F    1           10     48067 3        1      3408        4   978300275       F    1           10     48067 4        1      2355        5   978824291       F    1           10     48067 
 
2. concat合并 2.1 函数定义 pandas.concat(objs, axis=0, join=‘outer’, ignore_index=False) 
objs:一个列表,内容可以是DataFrame或者Series,可以混合 
axis:默认是0代表按行合并,如果等于1代表按列合并 
join:合并的时候索引的对齐方式,默认是outer join,也可以是inner join 
ignore_index:是否忽略掉原来的数据索引 
 
DataFrame.append(other, ignore_index=False) 
append只有按行合并,没有按列合并,相当于concat按行的简写形式
other:单个dataframe、series、dict,或者列表 
ignore_index:是否忽略掉原来的数据索引 -2.2 合并示例  
 
原始数据:1 2 3 4 5 6 7 8 9 10 11 12 13 14 df1 = pd.DataFrame({'A' : ['A0' , 'A1' , 'A2' , 'A3' ],                     'B' : ['B0' , 'B1' , 'B2' , 'B3' ],                     'C' : ['C0' , 'C1' , 'C2' , 'C3' ],                     'D' : ['D0' , 'D1' , 'D2' , 'D3' ],                     'E' : ['E0' , 'E1' , 'E2' , 'E3' ]                    }) df2 = pd.DataFrame({ 'A' : ['A4' , 'A5' , 'A6' , 'A7' ],                      'B' : ['B4' , 'B5' , 'B6' , 'B7' ],                      'C' : ['C4' , 'C5' , 'C6' , 'C7' ],                      'D' : ['D4' , 'D5' , 'D6' , 'D7' ],                      'F' : ['F4' , 'F5' , 'F6' , 'F7' ]                    })                                        print (df1, '\n' , df2)
1 2 3 4 5 6 7 8 9 10     A   B   C   D   E 0   A0  B0  C0  D0  E01   A1  B1  C1  D1  E12   A2  B2  C2  D2  E23   A3  B3  C3  D3  E3     A   B   C   D   F 0   A4  B4  C4  D4  F41   A5  B5  C5  D5  F52   A6  B6  C6  D6  F63   A7  B7  C7  D7  F7
 
有无ignore_index的区别:
1 2 3 4 5 df3 = pd.concat([df1, df2]) df4 = pd.concat([df1, df2], ignore_index=True ) print (df3, '\n' , df4)
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18     A   B   C   D    E    F 0   A0  B0  C0  D0   E0  NaN1   A1  B1  C1  D1   E1  NaN2   A2  B2  C2  D2   E2  NaN3   A3  B3  C3  D3   E3  NaN0   A4  B4  C4  D4  NaN   F41   A5  B5  C5  D5  NaN   F52   A6  B6  C6  D6  NaN   F63   A7  B7  C7  D7  NaN   F7     A   B   C   D    E    F 0   A0  B0  C0  D0   E0  NaN1   A1  B1  C1  D1   E1  NaN2   A2  B2  C2  D2   E2  NaN3   A3  B3  C3  D3   E3  NaN4   A4  B4  C4  D4  NaN   F45   A5  B5  C5  D5  NaN   F56   A6  B6  C6  D6  NaN   F67   A7  B7  C7  D7  NaN   F7
 
默认为outer,使用inner如下:1 2 3 df5 = pd.concat([df1, df2], join='inner' ) print (df5)
1 2 3 4 5 6 7 8 9     A   B   C   D 0   A0  B0  C0  D01   A1  B1  C1  D12   A2  B2  C2  D23   A3  B3  C3  D30   A4  B4  C4  D41   A5  B5  C5  D52   A6  B6  C6  D63   A7  B7  C7  D7
 
十一、数据透视 1. 透视方法 1) stack 和 unstack 
stack和unstack互为逆操作
stack将列索引 转成最内层行索引 
而unstack将最内层行索引 转成列索引 
具体参考:pandas中DataFrame的stack()、unstack()和pivot()方法的对比_pandas pivot和stack区别-CSDN博客 
2) reset_index 和 pivot 
DataFrame.pivot(index, columns, values)
指定三列,依次为行索引、列索引、构建一个DataFrame
使用rest_index可实现逆操作
2. 透视示例 2.1 数据预处理 原始数据:
1 2 3 4 5 6 7 8 9 df = pd.read_csv(     "../datas/movielens-1m/ratings.dat" ,     header=None ,     names="UserID::MovieID::Rating::Timestamp" .split("::" ),     sep="::" ,     engine="python"  ) print (df.head())
 
1 2 3 4 5 6    UserID  MovieID  Rating  Timestamp 0        1      1193        5   978300760 1        1       661        3   978302109 2        1       914        3   978301968 3        1      3408        4   978300275 4        1      2355        5   978824291 
 
调用pd.to_datetime将时间戳转化为时间对象,通过访问对象的属性dt.month访问月份,并做统计操作1 2 3 4 5 6 df["pdate" ] = pd.to_datetime(df["Timestamp" ], unit='s' ) df_group = df.groupby([df['pdate' ].dt.month, 'Rating' ])['UserID' ].count() print (df_group.head())
1 2 3 4 5 6 7 pdate  Rating 1       1          1127        2          2608         3          6442         4          8400         5          4495  Name: UserID , dtype : int64  
 
2.2 使用透视 1) unstack 和 stack示例 
1 2 3 df_unstack = df_group.unstack() print(df_unstack.head()) 
 
1 2 3 4 5 6 7 Rating     1      2       3       4       5  pdate 1        1127   2608    6442    8400    4495 2         629   1464    3297    4403    2335 3         466   1077    2523    3032    1439 4        1048   2247    5501    6748    3863 5        4557   7631   18481   25769   17840 
 
绘制曲线1 2 df_unstack.plot() plt.show() 
2) reset_index 和 pivot示例 
1 2 3 df_reset = df_group.reset_index() print (df_reset.head())
 
1 2 3 4 5 6    pdate  Rating    pv 0       1        1   1127 1       1        2   2608 2       1        3   6442 3       1        4   8400 4       1        5   4495 
 
1 2 3 df_pivot = df_reset.pivot('pdate' , 'Rating' , 'pv' ) print (df_pivot.head())
 
1 2 3 4 5 6 7 Rating     1      2       3       4       5  pdate 1        1127   2608    6442    8400    4495 2         629   1464    3297    4403    2335 3         466   1077    2523    3032    1439 4        1048   2247    5501    6748    3863 5        4557   7631   18481   25769   17840