• Pandas


    1.Pandas支持读取的文件类型

    数据类型说明Pandas读取方法
    csv、tsv、txt逗号分隔、tab分割的纯文本文件pd.read_csv
    excel微软xls或者xlsx文件pd.read_excel
    mysql关系型数据库pd.read_sql

    2.文件读取

    1.读取纯文本文件
    • 读取csv,使用默认的标题行、逗号分隔符
      import pandas as pd
      
      # 读取文件
      fpath = './data/ratings.csv'
      ratings = pd.read_csv(fpath)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • fpath:文件路径
      • sep:数据分隔符
      • header
      • names:某些数据没有表头,可以自定义列名,数组类型
    • 查看前几行数据,默认前5行
      ratings.head()
      
      • 1
    • 查看数据形状
      ratings.shape
      
      • 1
    • 查看列索引
      ratings.columns
      
      • 1
    • 查看行索引
      ratings.index
      
      • 1
    • 查看每列的数据类型
      ratings.dtypes
      
      • 1
    2.读取excel文件
    import pandas as pd
    	
    fpath = './data/access_pvuv.xlsx'
    ratings = pd.read_excel(fpath)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    3.读取mysql

    在这里插入图片描述

    import pymysql
    import pandas as pd
    
    conn = pymysql.connect(
    	host="127.0.0.1",
    	user="admin",
    	password="password",
    	database="test",
    	charset="utf8"
    )
    
    mysql_page = pd.read_sql("select * from crazyant_pvuv", conn=conn)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.Pandas数据结构

    1.DataFrame:二维数据,整个表格,多行多列)

    在这里插入图片描述

    1.定义
    • DataFrame是一个表格型的数据结构
    • 每列可以是不同的值类型(数值、字符串、布尔值等)
    • 既有行索引index,也有列索引columns
    • 可以被看作是由Series组成的字典
    2.创建DataFrame常用方法
    • 1.读取纯文本文件

    • 2.读取excel文件

    • 3.读取mysql数据库

    • 4.从数据源创建

      import pandas as pd
      
      data = {
          "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)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      	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

    2.Series:一维数据,一行或一列

    1.定义
    • Series是一种类似于一维数组的对象,类似于python字典,它由一组数据(可以是不同数据类型)以及一组与之相关的数据标签(即索引)组成
    2.创建Series常用方法
    • 1.使用列表数据生成一个最简单的Series

      import pandas as pd
      s1 = pd.Series([1, 'a', 5, True, [1]])
      
      • 1
      • 2
      0       1
      1       a
      2       5
      3    True
      4     [1]
      dtype: object
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 获取索引
        s1.index  # RangeIndex(start=0, stop=5, step=1)
        
        • 1
      • 获取数据
        s1.values  # array([1, 'a', 5, True, list([1])], dtype=object)
        
        • 1
    • 2.创建一个具有标签索引的Series

      import pandas as pd
      s2 = pd.Series([1, 'a', 5, True, [1]], index=['a', 'b', 'c', 'd', 'e'])
      
      • 1
      • 2
      a       1
      b       a
      c       5
      d    True
      e     [1]
      dtype: object
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 根据索引取单个值
        s2['a']   # 1
        type(s2['a'])  # int
        
        • 1
        • 2
      • 根据索引取多个值
        s2[['a', 'b']]
        '''
        a    1
        b    a
        dtype: object
        '''
        type(s2[['a', 'b']])  # pandas.core.series.Series
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
    • 2.使用Python字典创建Series

      import pandas as pd
      sdata = {'Ohio': 35000, 'Texas': 72000, 'Oregon': 16000, 'Utah': 5000}
      s3 = pd.Series(sdata)
      
      • 1
      • 2
      • 3
      Ohio      35000
      Texas     72000
      Oregon    16000
      Utah       5000
      dtype: int64
      
      • 1
      • 2
      • 3
      • 4
      • 5

    3.从DataFrame中查询出Series

    1.概念
    • 1.如果只查询一行、一列,返回的是pd.Series
    • 2.如果查询多行、多列,返回的是pd.DataFrame
    2.演示
    • 获取state索引列数据
      import pandas as pd
      data = {
          "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)
      type(df['state'])  # pandas.core.series.Series
      # 查询第一行
      # type(df.loc[0])  # pandas.core.series.Series
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • 获取state、year索引列数据
      import pandas as pd
      
      df[['state', 'year']]
      '''
      	state	year
      0	Ohio	2000
      1	Ohio	2001
      2	Ohio	2002
      3	Nevada	2001
      4	Nevada	2002
      '''
      
      type(df[['state', 'year']])  # pandas.core.frame.DataFrame
      
      
      # 查询前两行
      # type(df.loc[0: 1])  # pandas.core.frame.DataFrame
      # df.loc[0: 1]  # 包含尾部索引
      '''
      state	year	pop
      0	Ohio	2000	1.5
      1	Ohio	2001	1.7
      '''
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23

    4.Pandas数据查询

    1.df.loc

    1.定义
    • 根据行、列的标签查询
    2.示例演示(以下方法行列均适应)
    • 1.数据读取

      df.read_csv('./data/beijing_tianqi_2018.csv')
      
      • 1
    • 2.设置索引为日期,方便按日期筛选

      df.set_index('year', drop=True, append=False, inplace=False, verify_integrity=False)
      
      • 1
      • drop:是否删除作为索引使用的列,默认删除
      • append:将序列添加到索引中,形成多级序列
      • inplace:是否返回在原序列上进行修改,默认否,返回一个新的序列
      • verify_integrity:检查索引是否重复。默认是False
    • 3.数据预处理(将温度的后缀°C去掉)

      # 所有行,bWendu列       bWendu列转为字符串,去除°C,然后转换为整形
      df.loc[:, "bWendu"] = df["bWendu"].str.replace("°C", "").astype("int32")
      df.loc[:, "yWendu"] = df["yWendu"].str.replace("°C", "").astype("int32")
      
      • 1
      • 2
      • 3
    • 4.使用单个label值查询数据

      # 单元格 数据,得到一个具体的值
      df.loc['2018-01-03', 'bWendu']
      
      • 1
      • 2
    • 5.使用值列表批量查询

      # 一行两列 数据,得到一个Series,即:1月3日的最高温度和最低温度
      df.loc['2018-01-03', ['bWendu', 'yWendu']]
      
      • 1
      • 2
      # 一列两行 数据,得到一个Series,即:1月3日和1月4日的最高温度
      df.loc[['2018-01-03', '2018-01-04'], 'bWendu']
      
      • 1
      • 2
      # 两行两列 数据,得到一个DataFrame
      df.loc[['2018-01-03', '2018-01-04'], ['bWendu', 'yWendu']]
      
      • 1
      • 2
    • 6.使用数值区间进行范围查询(区间包含开始,也包含结束,和列表有所不同)

      # 行index区间
      # 获取1月3号到1月6号的最高温度
      df.loc['2018-01-03':'2018-01-06', 'bWendu']
      
      • 1
      • 2
      • 3
      # 列index区间
      # 获取1月3号最高温度到风向的所有列
      df.loc['2018-01-03', 'bWendu':'fengxiang']
      
      • 1
      • 2
      • 3
      # 行列都按区间查询
      df.loc['2018-01-03':'2018-01-06', 'bWendu':'fengxiang']
      
      • 1
      • 2
    • 7.使用条件表达式查询

      # 查询最高温度大于10°C的天气数据
      df.loc[df['bWendu'] > 10, :]
      
      • 1
      • 2
      # 查询最高温度小于30°,并且最低温度大于15°,并且是晴天,并且天气为优的数据
      df.loc[(df['bWendu'] < 30) & df['bWendu'] > 15) & df['tianqi'] == '晴') & df['aqiLevel'] == 1), :]
      
      • 1
      • 2
    • 8.调用函数查询

      def query_data(df):
      	return df.index.str.startswith('2018-09') & df['sqiLevel'] == 1
      
      # 查询9月份,空气质量为优的数据
      df.loc[query_data, :]
      
      • 1
      • 2
      • 3
      • 4
      • 5

    2.df.ilock

    1定义
    • 根据行列的数字位置查询

    3.df.where

    1.定义
    • 根据条件替换行或列中的值。如果满足条件,保持原来的值,不满足条件则替换为其他值。默认替换为NaN,也可以指定特殊值。
      DataFrame.where(cond, other=nan, inplace=False, axis=None, level=None, errors='raise', try_cast=False, raise_on_error=None)
      
      • 1
      • cond:布尔条件,如果 cond 为真,保持原来的值,否则替换为other
      • other:替换的特殊值
      • inplace:inplace为真则在原数据上操作,为False则在原数据的copy上操作
      • axis:行或列

    4.df.query

    1.定义
    • 根据条件过滤出符合的行或列

    5.Pandas新增数据列

    1.直接赋值

    • 类似于字典新增一个key
      # 给所有行,增加一个温差列   值为最高温度减去最低温度
      # df["bWendu"]是一个Series,两个Series相减,最终返回还是一个Series
      df.loc[:, "wencha"] = df["bWendu"] - df["yWendu"]
      
      • 1
      • 2
      • 3

    2.df.apply

    • 沿着axis轴,将一个Series传递给一个函数,该函数对传递的Series进行处理,返回一个新的Series

    • axis=0代表横轴,即二维坐标系中的x轴,也就是行

    • axis=1代表纵轴,即二维坐标系中的y轴,也就是列

      # 添加一列温度类型(如果最高温度大于33°就是高温;低于-10°就行就是低温;否则是常温)
      
      def get_wendu_type(x):
      	if x["bWendu"] > 30:
      		return "高温"
      	if x["yWendu"] < -10:
      		return "低温"
      	return "常温"
      
      df[:, "wendu_type"] = df.apply(get_wendu_type, axis=1)
      
      # 对温度类型进行统计
      df["wendu_type"].value_counts()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

    3.df.assign

    • 将某一列数据,作为函数参数传入,该函数返回一个新的对象,包含新的列和原来的列
    • 可以同时新增多列
      # 新增最高温度和最低温度对应的华氏温度列
      df.assign(
      	# 新增的列名                  x代表df
      	yWendu_huashi = lambda x : x["yWendu"] * 9 / 5 + 32
      	bWendu_huashi = lambda x : x["bWendu"] * 9 / 5 + 32
      )
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    4.按条件选择分组分别赋值

    • 按条件先选择数据,然后对这部分数据进行赋值新列
    • 将原数据按照温差进行分组(高温-低温>10,则认为温差大)
      # 创建一个新列
      df["wencha_type"] = ""
      # 按条件选择,然后赋值给上面创建的列
      df.loc[df["bWendu"] - df["yWendu"] > 10, "wencha_type"] = "温差大"
      df.loc[df["bWendu"] - df["yWendu"] <= 10, "wencha_type"] = "温差正常"
      
      • 1
      • 2
      • 3
      • 4
      • 5

    6.Pandas数据统计函数

    1.汇总类统计

    1.一下子提取所有数字列统计结果
    df.describe()
    
    • 1

    在这里插入图片描述

    2.查看平均值
    • 查看高温平均值
    df["bWendu"].mean()
    
    • 1
    3.查看最大值
    • 查看最高温
    df["bWendu"].max()
    
    • 1
    4.查看最小值
    • 查看最低温
    df["yWendu"].min()
    
    • 1

    2.唯一去重和按值计数

    1.唯一性去重(一般用于枚举、分类列)
    • 风向去重
      df['fengxiang'].unique()
      
      • 1
    • 天气去重
      df['tianqi'].unique()
      
      • 1
    • 风力去重
      df['fengli'].unique()
      
      • 1
    2.按值计数
    • 统计每个风向出现的次数
      df['fengxiang'].value_counts()
      
      • 1

    3.相关系数和协方差

    1.定义
    1.协方差
    • 1.衡量同向反向程度
    • 2.如果协方差为正,说明X、Y同向变化,协方差越大说明同向程度越高
    • 3.如果协方差为负,说明X、Y反向变化,协方差越小说明反向程度越高
    2.相关系数
    • 1.衡量相似程度
    • 2.当他们相关系数为1时,说明两个变量变化时的正相似度最大
    • 3.当他们相关洗漱为-1时,说明两个变量变化时的反相似度最大
    2.用途
    • 1.两只股票,是不是同涨同跌?程度多大?正常关还是负相关
    • 2.产品销量的波动,跟哪些因素正相关、负相关、程度有多大
    3.编码
    • 协方差矩阵
      df.cov()
      
      • 1

    在这里插入图片描述

    • 相关系数矩阵
      # 可以看出空气质量指数aqi和空气质量等级aqiLevel相关性为0.94,非常的相关
      df.corr()
      
      • 1
      • 2

    在这里插入图片描述

    • 单独查看
      # 空气质量和最高温度的相关系数
      df["aqi"].corr(df["bWendu"])  # 0.077067
      
      # 空气质量和最低温度的相关系数
      df["aqi"].corr(df["yWendu"])  # 0.026513
      
      # 空气质量和温差的相关系数
      df["aqi"].corr(df["bWendu"] - df["yWendu"])  # 0.216522
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

    7.Pandas缺失值处理

    1.isnullnotnull:检测是否是空值,可用于DataFrameSeries

    2.dropna:丢弃、删除缺失值

    • axis:删除行还是列,{0 or ‘index’, 1 or columns},default 0
    • how:如果等于any,则任何值为空都删除,如果等于all则所有值都为空才删除
    • inplace:如果为True则修改当前df,否则返回新的df,默认返回新的

    3.fillna:填充空值

    • value:用于填充的值,可以是单个值,或者字典(key是列名,value是值)
    • method:等于ffill,使用前一个不为空的值填充forward fill,等于bfill,使后一个不为空的值填充backword fill
    • axis:按行还是列填充,{0 or ‘index’, 1 or columns}
    • inplace:如果为True则修改当前df,否则返回新的df,默认返回新的

    4.事例演示

    1.数据如下

    在这里插入图片描述

    2.读取excel
    # 跳过前两行读取
    studf = pd.read_excel('./data/study_excel.xlsx', skiprows=2)
    
    • 1
    • 2

    在这里插入图片描述

    3.检测空值
    studf.isnull()
    
    • 1

    在这里插入图片描述

    3.1.单列检测空值
    studf["分数"].isnull()
    
    • 1
    3.2.筛选没有空分数的所有行
    studf.loc[studf["分数"].notnull(), :]
    
    • 1

    在这里插入图片描述

    4.删除掉全是空值的列
    # 在元数据基础上删除全是空值的列
    studf.dropna(axis="columns", how="all", inplace=True)
    
    • 1
    • 2

    在这里插入图片描述

    5.删除掉全是空值的行
    # 在元数据基础上删除全是空值的行
    studf.dropna(axis="index", how="all", inplace=True)
    
    • 1
    • 2

    在这里插入图片描述

    6.将分数列为空的填充为0分
    studf.fillna({"分数": 0})
    # 等同于
    # studf.loc[:, "分数"] = studf['分数'].fillna(0)
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    7.将姓名的缺失值填充
    # 使用前一个不为空的值进行填充
    studf.loc[:, "姓名"] = studf["姓名"].fillna(method="ffill")
    
    • 1
    • 2

    在这里插入图片描述

    8.将清洗好的excel保存
    # index=False:去除索引列
    studf.to_excel('./data/result_student.xlsx', index=False)
    
    • 1
    • 2

    在这里插入图片描述

    8.SettingWithCopyWarning告警处理

    1.原数据如下

    在这里插入图片描述

    2.复现问题
    • 1.只选出3月份的数据,用于分析
      condition = df["ymd"].str.startswith("2018-03")
      # 设置温差列(报错)
      df[condition]["wencha"] = df["bWendu"] - df["yWendu"]
      # 查看结果
      df[condition].head()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      在这里插入图片描述
      在这里插入图片描述
    3.原因
    • 发出告警的代码:df[condition]["wencha"] = df["bWendu"] - df["yWendu"]
    • 相当于:df.get("condition").set("wencha")
    • 第一步的get发出了报警,链式操做其实是两个步骤,先getset
    • get得到的dataframe可能是view(子df),也可能是copy(新的df)pandas发出警告。
    • 核心要诀:pandas的dataframe的修改写操做,只允许在源dataframe上进行
    4.解决方法
    • 1.将get+set的两步操做,变成set的一步操做
      df.loc[condition, 'wen_cha'] = df["bWendu"] - df["yWendu"]
      df[condition].head()
      
      • 1
      • 2
      在这里插入图片描述
    • 2.使用copy复制dataframe
      df_month3 = df[condition].copy()
      df_month3[condition]["wencha"] = df["bWendu"] - df["yWendu"]
      df_month3.head()
      
      • 1
      • 2
      • 3
      在这里插入图片描述
    5.提示
    • Pandas不允许先筛选子dataframe,再进行修改写入
    • 要么使用.loc实现一个步骤直接修改源dataframe
    • 要么先复制一个新的dataframe,再在该对象上进行修改写入

    9.Pandas数据排序

    1.对Series排序
    1.函数及参数说明
    Series.sort_values(ascending=True, inplace=False)
    
    • 1
    • ascending:默认为True升序排序,False为降序排序
    • inplace:修改原始数据还是复制一份新的数据
    2.对高温列进行排序
    df["bWendu"].sort_values()
    
    • 1
    2.对DataFrame排序
    1.函数及参数说明
    DataFrame.sort_values(by, ascending=True, inplace=False)
    
    • 1
    • bystrList,单列排序或者多列排序
    • ascending:默认为True升序排序,False为降序排序
    • inplace:修改原始数据还是复制一份新的数据
    2.单列排序
    df.sort_values(by='aqi')
    
    • 1
    3.多列排序
    df.sort_values(by=['bWendu', 'yWendu'], ascending=[True, False])
    
    • 1

    10.Pandas字符串处理

    1.使用方法
    • 先获取Series,再在str属性上调用函数
      • 只能在字符串列上使用
      • DataFrame上没有str属性和处理方法
      • Series.str并不是python中的原生字符串,而是一套自己的方法,不过大部分和原生str很像
    2.官方地址
    3.实例演示
    • object列都是字符串列,可以直接使用str的方法
      在这里插入图片描述
      在这里插入图片描述

    • 1.获取Seriesstr属性

    df["bWendu"].str
    
    • 1
    • 2.字符串替换函数
    df["bWendu"].str.replace("°C""")
    
    • 1
    • 3.判断是不是数字
    df["bWendu"].str.isnumeric()
    
    • 1
    • 4.获取字符串长度
    df["bWendu"].str.len()
    
    • 1
    • 5.判断字符串是否以什么开头
    condition = df["ymd"].str.startswith("2018-03")
    df[condition].head()
    
    • 1
    • 2

    在这里插入图片描述

    • 6.链式多次处理
    df["ymd"].str.replace("-", "").str.slice(0, 6)
    # df["ymd"].str.replace("-", "").str[0:6]
    
    • 1
    • 2
    • 7.正则表达式
    # 1.新增一列中文日期
    def get_nianyueri(x):
    	year,month,day = x["ymd"].split("-)
    	return f"{year}{month}{day}日"
    df["中文日期"] = df.apply(get_nianyueri, axis=1)
    
    # 2.去掉中文日期这一列中的年月日中文字样
    # 方法一:
    df["中文日期"].str.replace("年", "").str.replace("月", "").str.replace("日", "")
    # 方法二:
    df["中文日期"].str.replace("[年月日]", "")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    11.Pandas的axis参数

    1.详解
    • axis=0 或者 “index”
      • 如果是单行操做,就值的是某一行
      • 如果是聚合操作,指的是跨行,想象一下从上往下挤压
    • axis=1 或者 ”columns“
      • 如果是单列操做,就指的是某一列
      • 如果是聚合操做,指的是跨列,想象一下从左往右挤压
    2.示例
    1.构造数据
    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame(
        np.arange(12).reshape(3,4),
        columns=["A", "B", "C", "D"]
    )
    
    '''
    	A	B	C	D
    0	0	1	2	3
    1	4	5	6	7
    2	8	9	10	11
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    2.单列drop,就是删除某一列
    df.drop("A", axis=1)
    
    '''
    	B	C	D
    0	1	2	3
    1	5	6	7
    2	9	10	11
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    3.单行drop,就是删除某一列
    df.drop(1, axis=0)
    
    '''
    	A	B	C	D
    0	0	1	2	3
    2	8	9	10	11
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    4.跨行求取平均值
    df.mean(axis=0)
    
    '''
    A    4.0
    B    5.0
    C    6.0
    D    7.0
    dtype: float64
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    5.跨列求取平均值
    df.mean(axis=1)
    
    '''
    0    1.5
    1    5.5
    2    9.5
    dtype: float64
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    6.增加一列sum_value,保存每行的和
    def get_sum_value(x):
    	return x["A"] + x["B"] + x["C"] + x["D"]
    
    df["sum_value"] = df.apply(get_sum_value, axis=1)
    
    '''
    	A	B	C	D	sum_value
    0	0	1	2	3	6
    1	4	5	6	7	22
    2	8	9	10	11	38
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    12.Pandas的索引index

    1.用途
    • 1.更方便的数据查询
    • 2.使用index可以获得性能提升
    • 3.自动的数据对齐功能
    • 4.更多更强大的数据结构支持
    2.示例
    1.使用index查询数据
    • 1.读取数据

      import pandas as pd
      
      fpath = './data/ratings.csv'
      df = pd.read_csv(fpath)
      
      • 1
      • 2
      • 3
      • 4

      在这里插入图片描述

    • 2.设置索引

      df.set_index("userId", inplace=True, drop=False)
      
      • 1

      在这里插入图片描述

    • 3.使用索引查询

      # 使用index查询
      df.loc[500].head()
      
      # 相当于
      df.loc["userId" == 500].head()
      
      • 1
      • 2
      • 3
      • 4
      • 5

      在这里插入图片描述

    2.使用index提升性能
    • 如果index是唯一的,Pandas会使用哈希表优化,查询性能O(1)
    • 如果index不是唯一,但是有序,``Pandas会使用二分查找算法,查询性能O(logN)
    • 如果index是完全随机的,那么每次查询都要扫描全表,查询性能为O(N)
    • 实验一:完全随机的顺序查询
      from sklearn.utils import shuffle
      
      df_shuffle = shuffle(df)
      # 检查索引是否是递增的
      df_shuffle.index.is_monotonic_increasing  # False
      # 检查索引是否唯一
      df_shuffle.index.is_unique  # False
      # 计时,查询 id=500的数据性能
      %timeit df_shuffle.loc[500]  # 498 µs ± 28.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 实验二:将index排序后的查询
      df_sorted = df_shuffle.sort_index()
      # 检查索引是否是递增的
      df_sorted .index.is_monotonic_increasing  # True
      # 检查索引是否唯一
      df_sorted .index.is_unique  # False
      # 计时,查询 id=500的数据性能
      %timeit df_sorted.loc[500]  # 231 µs ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    3.使用index能自动对齐数据
    • 包括series和dataframe
      import pandas as pd
      
      s1 = pd.Series([1, 2, 3], index=list("abc"))
      
      '''
      a    1
      b    2
      c    3
      dtype: int64
      '''
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      s1 = pd.Series([2, 3, 4], index=list("bcd"))
      
      '''
      b    2
      c    3
      d    4
      dtype: int64
      '''
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      s1 + s2
      
      '''
      a    NaN
      b    4.0
      c    6.0
      d    NaN
      dtype: float64
      '''
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    4.使用index更多更强大的数据结构支持
    • CategoricalIndex,基于分类数据的Index,提升性能
    • MultiIndex,多维索引,用于groupby多维聚合后结果等
    • DatetimeIndex,时间类型索引,强大的日期和时间的方法支持

    13.Pandas的Merge语法

    1.说明

    • Pandas的Merge,相当于Sq的Join,将不同的表按key关联到一个表

    2.用法

    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, )
    
    • 1
    • left:要merge的dataframe或series
    • right:要merge的dataframe或series
    • how:join类型,‘left’,‘right’,‘outer’,‘inner’
    • on:join的key,left和right都要有这个key
    • left_on:left的df或series的key
    • right_on:right的df或series的key
    • left_index:使用index而不是普通的column做join
    • right_index:使用index而不是普通的column做join
    • sort:排序
    • suffixes:合并表时重名字段自定义命名
    • copy
    • indicator

    3.电影数据集join实例

    1.电影评分数据集
    • 1.用户对电影的评分数据:ratings.dat

      import pandas as pd
      
      df_ratings = pd.read_csv(
          "./data/ratings.dat",
          sep="::",  # 分隔符为两个字符时会被识别为正则表达式,指定engine=python来告诉pandas他是一个字符串
          engine="python",
          names=["UserID", "MovieID", "Rating", "Timestamp"]
      )
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      在这里插入图片描述

    • 2.用户本身的信息数据:users.dat

      df_users = pd.read_csv(
          "./data/users.dat",
          sep="::",  # 
          engine="python",
          names="UserID::Gender::Age::Occupation::Zip-code".split("::")
      )
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      在这里插入图片描述

    • 3.电影本身的数据:movies.dat

      df_momvies = pd.read_csv(
          "./data/movies.dat",
          sep="::",  # 
          engine="python",
          names="MovieID::Title::Geners".split("::")
      )
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      在这里插入图片描述

    • 4.用户和评分join

      df_ratings_users = pd.merge(
          df_ratings, df_users, left_on="UserID", right_on="UserID", how="inner"
      )
      
      • 1
      • 2
      • 3

      在这里插入图片描述

    • 5.用户和评分join的结果再和电影join

      df_ratings_movies = pd.merge(
          df_ratings, df_momvies, left_on="MovieID", right_on="MovieID", how="inner"
      )
      
      • 1
      • 2
      • 3

      在这里插入图片描述

    2.理解merge时数量的对齐关系
    1.关系理解
    • one-to-one:关联的key都是唯一的
    • one-to-many:左边key唯一,右边key不唯一
    • many-to-many:左边右边key都不是唯一的
    2.一对一关系的merge
    • 1.数据表如下
      在这里插入图片描述

    • 2.合并

      left = pd.DataFrame({
          "sno": [11, 12, 13, 14],
          "name": ["name_a", "name_b", "name_c", "name_d"]
      })
      
      right = pd.DataFrame({
          "sno": [11, 12, 13, 14],
          "age": ["21", "22", "23", "24"]
      })
      
      pd.merge(left, right, on="sno")
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      在这里插入图片描述

    2.一对多关系的merge
    • 1.数据表如下
      在这里插入图片描述
    • 2.合并
      left = pd.DataFrame({
          "sno": [11, 12, 13, 14],
          "name": ["name_a", "name_b", "name_c", "name_d"]
      })
      
      right = pd.DataFrame({
          "sno": [11, 11, 11, 12, 12, 13],
          "grade": ["语文88", "数学90", "英语75", "语文66", "数学55", "英语29"]
      })
      
      pd.merge(left, right, on="sno")
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      在这里插入图片描述
    2.多对多关系的merge
    • 1.数据表如下
      在这里插入图片描述
    • 2.合并
      left = pd.DataFrame({
          "sno": [11, 11, 12, 12, 12],
          "爱好": ["篮球", "羽毛球", "乒乓球", "篮球", "足球"]
      })
      
      right = pd.DataFrame({
          "sno": [11, 11, 11, 12, 12, 13],
          "grade": ["语文88", "数学90", "英语75", "语文66", "数学55", "英语29"]
      })
      
      pd.merge(left, right, on="sno")
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      在这里插入图片描述
    3.理解left joinright joininner joinouter join时数量的对齐关系
    1.图示

    在这里插入图片描述

    2.实例
    • 1.数据如下
      在这里插入图片描述在这里插入图片描述

      left = pd.DataFrame({
          "key": ["K0", "K1", "K2", "K3"],
          "A": ["A0", "A1", "A2", "A3"],
          "B": ["B0", "B1", "B2", "B3"]
      })
      
      right = pd.DataFrame({
          "key": ["K0", "K1", "K4", "K5"],
          "C": ["C0", "C1", "C2", "C3"],
          "D": ["D0", "D1", "D2", "D3"]
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • 2.inner join,默认,左右都有的key,才会出现在结果里

      pd.merge(left, right, how='inner')
      
      • 1

      在这里插入图片描述

    • 3.left join,左边的都会出现在结果里,右边匹配不到的以Null填充

      pd.merge(left, right, how='left')
      
      • 1

      在这里插入图片描述

    • 4.right join,右边的都会出现在结果里,左边匹配不到的以Null填充

      pd.merge(left, right, how='right')
      
      • 1

      在这里插入图片描述

    • 5.outer join,左边右边的都会出现在结果里,相互匹配不到的以Null填充

      pd.merge(left, right, how='outer')
      
      • 1

      在这里插入图片描述

    4.重复key
    • 1.图示
      在这里插入图片描述 在这里插入图片描述

    • 2.使用suffixes默认值

      pd.merge(left, right, on="key")
      
      • 1

      在这里插入图片描述

    • 3.自定义重名的key

      pd.merge(left, right, on="key", suffixes=("_left", "_right"))
      
      • 1

      在这里插入图片描述

    14.Pandas的Concat合并

    1.语法
    1.说明
    • 使用某种合并方式(inner/outer)
    • 沿着某个轴向(axis=0/1)
    • 把多个Pandas对象(DataFrame/Series)合并成一个
    2.concat语法
    pd.concat(objs, axis=0, join="outer", ignore_index=False)
    
    • 1
    • objs:一个列表,内容可以是DataFrame或者Series,可以混合
    • axis:默认是0,代表按行合并,如果等于1代表按列合并
    • join:合并的时候索引的对齐方式,默认是outer join,也可以是inner join
    • ignore_index:是否忽略掉原来的数据索引
    3.append语法
    df.append(other, ignore_index=False)
    
    • 1
    • append只有按行合并,并没有按列合并,相当于concat按行合并的简写
    • other:单个dfseriesdict或者列表
    • ignore_index:是否忽略掉原来的数据索引
    2.使用场景
    • 批量合并想同格式的Excel
    • DataFrame添加行
    • DataFrame添加列
    3.使用pandas.concat合并数据
    1.数据准备
    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"]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述在这里插入图片描述

    2.默认concat,参数为axis=0、join=outer、ignore_index=False
    pd.concat([df1, df2])
    
    • 1

    在这里插入图片描述

    3.使用ignore_index=True忽略原来的索引
    pd.concat([df1, df2], ignore_index=True)
    
    • 1

    在这里插入图片描述

    4.使用join=inner过滤掉不匹配的列
    pd.concat([df1, df2], ignore_index=True, join="inner")
    
    • 1

    在这里插入图片描述

    5.使用axis=1进行列合并
    pd.concat([df1, df2], axis=1)
    
    • 1

    在这里插入图片描述

    6.DdataFrame和Series混合关联
    • 增加一列
    s1 = pd.Series(list(range(4)), name='F')
    pd.concat([df1, s1], axis=1)
    
    • 1
    • 2

    在这里插入图片描述

    • 增加一行
    # 添加行
    s2 = pd.Series({i: i+str(4) for i in "ABCDE"}, name=4)
    df1.append(s2)
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    4.使用DataFrame.append按行合并数据
    1.数据准备

    在这里插入图片描述在这里插入图片描述

    df1 = pd.DataFrame(
        [
            [1, 2],
            [3, 4]
        ],
        columns=list("AB")
    )
    
    df2 = pd.DataFrame(
        [
            [5, 6],
            [7, 8]
        ],
        columns=list("AB")
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    2.给df1添加一个名为df2的dataframe
    df1.append(df2)
    
    • 1

    在这里插入图片描述

    3.忽略原索引
    df1.append(df2, ignore_index=True)
    
    • 1

    在这里插入图片描述

    4.可以一行一行的给DataFrame添加数据
    • 低性能版本
    df = pd.DataFrame(
        columns=["A"]
    )
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    for i in range(5):
        df = df.append({"A": i}, ignore_index=True)
    df
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    • 高性能版本
    pd.concat(
    	# 数据量过大时,需要分批
        [pd.DataFrame([i], columns=["A"]) for i in range(5)],
        ignore_index=True
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    15.Pandas批量拆分与合并Excel文件

    1.实例演示
    1.将一个大的Excel等份拆成多个小的Excel
    • 1.数据读取
    import pandas as pd
    
    df_source = pd.read_excel('./data/crazyant_blog_articles.xlsx')
    df_source.head()
    df_source.shape  # (258, 3)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    • 2.计算拆分后的每个excel的行数
    # 拆分列表
    user_names = ['zs', 'ls', 'ww', 'zl', 'sq', 'qb']
    # 获取总行数
    total = df_source.shape[0]
    
    # 计算每个人的任务条目
    split_size = total // len(user_names)
    if split_size % len(user_names) != 0:
        split_size += 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 3.拆分成多个dataframe
    df_subs = []
    for idx, user_name in enumerate(user_names):
        # iloc的开始索引
        begin = idx * split_size
        # iloc的结束索引
        end = begin + split_size
        # 实现df按照iloc拆分
        df_sub = df_source.iloc[begin:end]
        # 将每个子df存入列表
        df_subs.append((idx, user_name, df_sub))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 4.将每个dataframe存入excel
    for idx, user_name, df_sub in df_subs:
        file_name = f"./split_dir/{idx}_{user_name}.xlsx"
        df_sub.to_excel(file_name, index=False)
    
    • 1
    • 2
    • 3
    2.将多个小的Excel合并成一个大的Excel,并且标记来源
    • 1.遍历文件夹,得到要合并的Excel名称列表
    import os
    
    excel_names = []
    for excel_name in os.listdir('./split_dir'):
        excel_names.append(excel_name)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 2.分别读取到dataframe
    df_list = []
    
    for index, excel_name in enumerate(excel_names):
        # 读取每个excel到df
        excel_path = f"./split_dir/{excel_name}"
        df_split = pd.read_excel(excel_path)
        # 得到username
        username = excel_name.replace(f"{index}_", "").split(".")[0]
        # 每个df添加1列,用户名
        df_split["username"] = username
        print(df_split)
        df_list.append(df_split)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 3.使用pd.concat进行合并
    df_merge = pd.concat(df_list)
    df_merge.shape  # (258, 4)
    df_merge.head()
    df_mergr["username"].value_counts()
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    在这里插入图片描述

    • 4.将合并后的dataframe输出到excel中
    # index=False:忽略每个表中自己的索引
    df_merge.to_excel(f"./split_dir/new_articles.xlsx", index=False)
    
    • 1
    • 2

    16.Pandas实现group by分组

    1.分组使用聚合函数做数据统计
    1.准备数据
    import pandas as pd
    import numpy as np
    
    %matplotlib inline  # 加这一句,能在jupyter notebook展示matplot图表
    
    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
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    2.单个group by查询所有数据列的统计
    df.groupby('A').sum()
    
    • 1

    在这里插入图片描述

    • 1.groupby中的A变成了数据的索引列
    • 2.因为要统计sum,但B列不是数字,所以被自动忽略掉
    • 3.按照A列分组,分为两组foobar,然后计算foobarCD列对应的值加和后的结果
    2.多个列groupby,查询所有数据列的统计
    df.groupby(['A', 'B']).mean()
    
    • 1

    在这里插入图片描述

    • ('A', 'B')成对变成了二级索引
    df.groupby(['A', 'B'], as_index=False).mean()
    
    • 1

    在这里插入图片描述

    3.同时查看多种数据统计
    df.groupby('A').agg([np.sum, np.mean, np.std])
    
    • 1

    在这里插入图片描述

    4.查看单列的结果数据统计
    df.groupby('A')['C'].agg([np.sum, np.mean, np.std])
    # df.groupby('A').agg([np.sum, np.mean, np.std])['C']
    
    • 1
    • 2

    在这里插入图片描述

    5.不同列使用不同的聚合函数
    df.groupby('A').agg({"C": np.sum, "D":np.mean})
    
    • 1

    在这里插入图片描述

    df.groupby('A').agg({'C':[np.mean,'sum'],'D':['count',np.std]})
    
    • 1

    在这里插入图片描述

    2.遍历groupby的结果理解执行流程
    1.遍历单个列聚合的分组
    g = df.groupby("A")
    for name, group in g:
        print(name)
        print(group)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    • 获取单个分组的数据
    g.get_group("bar")
    
    • 1

    在这里插入图片描述

    2.遍历多个列聚合的分组
    g = df.groupby(["A", "B"])
    for name, group in g:
        print(name)
        print(group)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    • 获取单个分组的数据
    g.get_group(('foo', 'two'))
    
    • 1

    在这里插入图片描述

    • 查看groupby后的C列,生成一个Series
    for name, group in g['C']:
        print(name)
        print(group)
        print(type(group))
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    3.实例分组探索天气数据
    1.准备数据
    import pandas as pd
    
    fpath = "./data/beijing_tianqi_2018.csv"
    df = pd.read_csv(fpath)
    # 替换温度后面的 °C
    df.loc[:, "bWendu"] = df["bWendu"].str.repace("°C", "").astype("int32")
    df.loc[:, "yWendu"] = df["yWendu"].str.repace("°C", "").astype("int32")
    df.head()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    2.查看每个月的最高温度
    • 新增一列月份
    df["month"] = df["ymd"].str[:7]
    df.head()
    
    • 1
    • 2

    在这里插入图片描述

    • 按照月份分组统计
    data = df.groupby("month")["bWendu"].max()
    
    • 1

    在这里插入图片描述

    type(data)  # pandas.core.series.Series
    data.plot()
    
    • 1
    • 2

    在这里插入图片描述

    2.查看每个月的最高温度、最低温度、平均空气质量指数
    group_data = df.groupby("month").agg({"bWendu": np.max, "yWendu": np.min, "aqi": np.mean})
    
    • 1

    在这里插入图片描述

    group_data.plot()
    
    • 1

    在这里插入图片描述

    17.Pandas的分层索引MultiIndex

    1.分层索引作用
    • 1.分层索引:在一个轴上向上拥有多个索引层级,可以表达更高维度的数据形式
    • 2.可以方便的进行数据筛选,如果有序则性能更好
    • 3.groupby等操作的结果,如果是多KEY,结果是封层索引
    • 4.一般不需要自己创建分层索引(MultiIndex有构造函数,但一般不用)
    2.实例演示
    1.数据展示
    • 以下为:百度、阿里巴巴、爱奇艺、京东四家公司的10天股票数据
      在这里插入图片描述
    2.Series的分层索引MultiIndex
    • 1.数据准备
    import pandas as pd
    
    %matplotlib inline
    
    stocks = pd.read_excel('./data/internet.xlsx')
    stocks.shape  # (12, 8)
    stocks.head(3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    stocks['公司'].unique()
    # array(["BIDU", "BABA", "IQ", "JD"], dtype=object)
    
    • 1
    • 2
    stocks.index
    # RangeIndex(start=0, stop=12, setp=1)
    
    • 1
    • 2
    stocks.groupby("公司")["收盘"].mean()
    
    • 1

    在这里插入图片描述

    • 2.分层索引MultiIndex
    ser = stocks.groupby(['公司', '日期'])["收盘"].mean()
    
    • 1

    在这里插入图片描述

    ser.index
    
    • 1

    在这里插入图片描述

    # 把二级索引变成列
    ser.unstack()
    
    • 1
    • 2

    在这里插入图片描述

    ser.reset_index()
    
    • 1

    在这里插入图片描述

    3.Series有多层索引怎样刷选数据
    • 1.指定个索引晒筛选
    ser = stocks.groupby(['公司', '日期'])["收盘"].mean()
    
    • 1

    在这里插入图片描述

    ser.loc["BIDU"]
    
    • 1

    在这里插入图片描述

    • 2.多层索引使用元组形式筛选
    # 
    ser.loc[("BIDU", "2019-10-02")]
    
    • 1
    • 2

    在这里插入图片描述

    • 3.多层索引使用切片形式筛选
    # 
    ser.loc[:, "2019-10-02"]
    
    • 1
    • 2

    在这里插入图片描述

    4.DataFrame的多层索引MultiIndex
    • 1.数据准备
    stocks.head()
    
    • 1

    在这里插入图片描述

    • 2.设置分层索引
    stocks..set_index(["公司", "日期"], inplace=True)
    
    • 1

    在这里插入图片描述

    • 3.查看分层索引
    stocks.index
    
    • 1

    在这里插入图片描述

    • 4.对分层索引进行排序
    stocks.sort_index(inplace=True)
    
    • 1

    在这里插入图片描述

    5.DataFrame有多层索引怎样刷选数据
    • 【重要知识】在选择数据时
      • 元组(key1, key2)代表筛选多层索引,其中key1是索引的第一级,key2是索引的第二级,比如:key1=JD, key2=2019-10-02
      • 列表 [key1, key2] 代表同一层级的多个KEY,其中key1key2是并列的同级索引,比如:key1=JD, key2=BABA
    stocks.loc["BIDU"]
    
    • 1

    在这里插入图片描述

    stocks.loc[("BIDU", "2019-10-02"), :]
    
    • 1

    在这里插入图片描述

    stocks.loc[("BIDU", "2019-10-02"), "开盘"]
    
    • 1

    在这里插入图片描述

    stocks.loc[["BIDU", "JD"], :]
    
    • 1

    在这里插入图片描述

    stocks.loc[(["BIDU", "JD"], "2019-10-03"), :]
    
    • 1

    在这里插入图片描述

    stocks.loc[(["BIDU", "JD"], "2019-10-03"), "收盘"]
    
    • 1

    在这里插入图片描述

    stocks.loc[("BIDU", ["2019-10-02", "2019-10-03"]), "收盘"]
    
    • 1

    在这里插入图片描述

    # slice(None)代表筛选这一索引所有的内容
    stocks.loc[(slice(None), ["2019-10-02", "2019-10-03"]), "收盘"]
    
    • 1
    • 2

    在这里插入图片描述

    stocks.reset_index()
    
    • 1

    在这里插入图片描述

    18.Pandas的数据转换函数map、apply、applymap

    1.数据转换函数对比
    • 1.map:只用于Series,实现每个值—>值的映射
    • 2.apply:用于Series实现每个值的处理,用于DataFrame实现某个轴的Series的处理
    • 3.applymap:只能用于DataFrame,用于处理该DataFrame的每个元素
    2.map用于Series值的转换
    1.将股票代码英文转换成中文名字
    import pandas as pd
    
    stocks = pd.read_excel("./data/internet.xlsx")
    stocks.head()
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    stocks["公司"].unique()
    
    • 1

    在这里插入图片描述

    2.使用Series.map(dict)进行转换
    • function的参数是Series的每个元素的值
    dict_company_names = {
    	"bidu": "百度",
    	"baba": "阿里巴巴",
    	"iq": "爱奇艺",
    	"jd": "京东"
    }
    stocks["中文公司1"] = stocks["公司"].str.lower().map(dict_company_names)
    stocks.head()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    3.使用Series.map(function)进行转换
    stocks["中文公司2"] = stocks["公司"].map(lambda x: dict_company_names[x.lower()])
    stocks.head()
    
    • 1
    • 2

    在这里插入图片描述

    3.apply用于Series和DataFrame的转换
    1.Series.apply(function),函数的参数是每个值
    stocks["中文公司3"] = stocks["公司"].apply(lambda x: dict_company_names[x.lower()])
    stocks.head()
    
    • 1
    • 2

    在这里插入图片描述

    2.DataFrame.apply(function),函数的参数是Series
    stocks["中文公司3"] = stocks.apply(lambda x: dict_company_names[x["公司"].lower()], axis=1)
    stocks.head()
    
    • 1
    • 2

    在这里插入图片描述

    • 1.apply是在stocks这个DataFrame上进行调用;
    • 2.lambda x,x是一个Series,因为指定了axis=1,所以Series的key是由列名组成,可以使用x["公司"]获取公司这一列数据,然后进行处理
    4.applymap用于DataFrame所有值的转换
    sub_df = stocks[["收盘", "开盘", "高", "低", "交易量"]]
    sub_df.head()
    
    • 1
    • 2

    在这里插入图片描述

    • 将上述数值取整
    sub_df.applymap(lambda x: int(x))
    sub_df
    
    • 1
    • 2

    在这里插入图片描述

    • 方法二:
    stocks.loc[:, ["收盘", "开盘", "高", "低", "交易量"]] = sub_df.applymap(lambda x: int(x))
    stocks.head()
    
    • 1
    • 2

    在这里插入图片描述

    19.Pandas对groupby后的数据应用apply

    1.图解说明

    在这里插入图片描述

    2.GroupBy(function)
    • function的第一个参数是dataframe
    • function的返回结果,可以是dataframe、series、单个值,甚至和输入DataFrame完全没有关系
    3.实例演示
    1.怎样对数值列按分组的归一化
    • 1.归一化:将不同范围的数值进行归一化,映射到【0-1】区间
      • 更容易做到数据的横向对比,比如价格字段是几百到几千,增幅字段是0到100
      • 机器学习模型学的更快,性能更好
        在这里插入图片描述
    • 2.用户对电影评分的归一化
    import pandas as pd
    
    ratings = pd.read_csv(
        "./data/ratings.dat",
        sep="::",
        engine="python",
        names="UserID::MovieID::Rating::Timestamp".split("::")
    )
    ratings.head()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    • 实现按照用户ID分组,然后对其中一列归一化
    def ratings_norm(df):
        min_value = df["Rating"].min()
        max_value = df["Rating"].max()
        df["Rating_norm"] = df["Rating"].apply(lambda x: (x - min_value) / (max_value - min_value))
        return df
    ratings = ratings.groupby("UserID").apply(ratings_norm)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    ratings[ratings["UserID"] == 1].head()
    
    • 1

    在这里插入图片描述

    2.怎样获取每个分组的TOPN数据
    fpath = "./data/beijing_tianqi_2018.csv"
    df = pd.read_csv(fpath)
    # 替换温度后面的 °C
    df.loc[:, "bWendu"] = df["bWendu"].str.repace("°C", "").astype("int32")
    df.loc[:, "yWendu"] = df["yWendu"].str.repace("°C", "").astype("int32")
    # 增加一列月份
    df["month"] = df["ymd"].str[:7]
    df.head()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    def getWenduTopN(df, topn):
        """
        df: 每个月份分组group的df
        """
        # df.sort_values(by="bWendu"):按高温一列升序排序
        # [["ymd", "bWendu"]]:取年月日和高温两列数据
        # [-topn:]:因为是升序,所以取-topn
        return df.sort_values(by="bWendu")[["ymd", "bWendu"]][-topn:]
    
    df.groupby("month").apply(getWenduTopN, topn=2).head()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    20.Pandas使用stack和pivot实现数据透视

    1.作用
    • 将列式数据变成二维交叉形式,便于分析,叫做重塑或透视
      在这里插入图片描述
    2.流程
    • 1.经过统计得到多维度指标数据
    • 2.使用unstack实现数据二维透视
    • 3.使用pivot简化透视
    • 4.stack、unstack、pivot的语法
    3.经过统计得到多维度指标数据
    1.实例:统计得到电影评分数据集,每个月份的每个分数被评分多少次(月份、分数1-5、次数)
    • 1.读取数据
    import pandas as pd
    import numpy as np
    
    %matplotlib inline
    
    df = pd.read_csv(
        "./data/ratings.dat",
        header=None,
        sep="::",
        engine="python",
        names="UserID::MovieID::Rating::Timestamp".split("::")
    )
    df.head()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    • 2.增加一列时间日期
    # 增加一列时间日期,由秒格式的Timestamp字段转换而来
    df["pdate"] = pd.to_datetime(df["Timestamp"], unit="s")
    df.head()
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    • 3.查看各个字段类型
    df.dtypes
    
    • 1

    在这里插入图片描述

    • 4.实现数据统计
    • 1.统计
    # 按照月份和评分分组,创建两个索引,取Rating这个series,统计后倒序排列(方便验证结果)
    df_group = df.groupby([df["pdate"].dt.month, "Rating"])["Rating"].agg({"pv": np.size}).sort_values("pdate", ascending=False)
    
    • 1
    • 2

    在这里插入图片描述

    • 2.验证12月份5分的评价有多少条
      • 1.新增一列月份
        df["month"] = df["pdate"].dt.month
        
        • 1
      • 2.过滤12月份评分为5分的数据,按照评分统计条数
        df[(df["Rating"] == 5) & (df["month"]==12)]["Rating"].value_counts()
        
        • 1
      • 3.得到结果为:5 26760 Name: Rating, dtype: int64
    2.使用unstack实现数据二维透视
    • 1.使用unstack实现透视
    df_stack = df_group.unstack()
    
    • 1

    在这里插入图片描述

    df_stack.plot()
    
    • 1

    在这里插入图片描述

    • 2.使用stack还原
    df_stack.stack().head()
    
    • 1

    在这里插入图片描述

    3.使用pivot简化透视
    df_group.head(20)
    
    • 1

    在这里插入图片描述

    df_reset = df_group.reset_index()
    df_reset.head()
    
    • 1
    • 2

    在这里插入图片描述

    df_pivot = df_reset.pivot("pdate", "Rating", "pv")
    df_pivot.head()
    
    • 1
    • 2

    在这里插入图片描述

    df_pivot.plot()
    
    • 1

    在这里插入图片描述

    4.stack、unstack、pivot的语法
    • pivot:方法相当于对df使用set_index创建分层索引,然后使用unstack
    • stackDateFrame.stack(level=-1, dropna=True),将column变成index,类似把横放的书籍变成竖放
      • level:-1代表错层索引的最内层,可以通过0、1、2指定多层索引对应的层

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    图像质量指标:PSNR、SSIM、MSE
    IDEA中SVN 的使用
    OpenCL 介绍
    【刷题笔记9.24】LeetCode:对称二叉树
    Maven 的其它插件
    【经典文献】水下光学和声学成像:融合的时代?最新技术概述
    考古:MFC界面的自适应缩放(代码示例)
    TCP协议面试灵魂10问,建议收藏~
    革命性创新,动画杀手锏 @scroll-timeline
    U2-Net 使用嵌套 U 结构进行更深入的显着目标检测
  • 原文地址:https://blog.csdn.net/qq_42517220/article/details/126836718