Pandas

Pandas

一、Pandas简介

1. 什么是Pandas?

pandas是基于Numpy实现的数据分析库。

Numpy的局限在于只能处理同一数据元素的数组,但实践当中数据元素的类型非常复杂。Pandas可以破除这种局限,但只能处理二维数据表。

Pandas就是用于操作一张二维数据表的工具。

2. Pandas的两种数据类型-Series和DataFrame

(1) Series(系列):特殊的一维数组

# 创建Series
pd.Series(data,index = 列表)
"""
data 可以是一个列表、元组或者字典
index 可选参数  用于显式的指定Series的行名(索引) 
      默认行名是从0开始的整数

当data是一个字典时,如果不指定index的值,字典的key就会作为Series的行名部分,字典的value作为数据部分
"""
 - Series的两个属性:index和values
     ```python
     se.index
     se.values
     ```
 - 获取某行值
     ```python
     se.loc[行名]
     ```
result = se.loc["red"]
print(result)
---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

Cell In[4], line 1
----> 1 result = se.loc["red"]
      2 print(result)


NameError: name 'se' is not defined
  • DataFrame(数据帧):特殊的二维数组

    pd.DataFrame(data,index = 列表,column = 列表)
    
    # data可以是列表、元组或字典
    # index是“行名”
    # column 是一个可选参数,显示地指定DataFrame的“列名”
    
- data是列表,每一个元素都是一个列表
import pandas as pd

data = [["小杰","男",20],["小红","女",19],["小明","男",21]]

df = pd.DataFrame(data,index = ["s1","s2","s3"],columns = ["name","gender","age"])
print(df)
   name gender  age
s1   小杰      男   20
s2   小红      女   19
s3   小明      男   21


- data是列表,每一个元素都是一个字典
# 当data的元素都是字典时,相当于自带了列名。
data = [
    {"name":"小杰","gender":"男","age":20},
    {"name":"小红","gender":"女","age":19},
    {"name":"小明","gender":"男","age":21}
]
df = pd.DataFrame(data)
print(df)
  name gender  age
0   小杰      男   20
1   小红      女   19
2   小明      男   21


- data是一个字典,字典的key作为DataFrame的列明,value作为DataFrame的数据

value可以是一个列表或者是一个值

data = {
    "name":["小杰","小红","小明"],
    "gender":["男","女","男"],
    "age":[20,19,21],
    #value是一个值
    "class":"一班"
}

df = pd.DataFrame(data,index = ["s1","s2","s3"])

#输出对齐
pd.set_option("display.unicode.east_asian_width", 
               True)

print(df)
    name gender  age class
s1  小杰     男   20  一班
s2  小红     女   19  一班
s3  小明     男   21  一班


- DataFrame属性

alt text

3. DataFrame的增删改查

  • 访问数据
df.loc[行名,列名]
df.iloc[行下标,列下标]

#获取某一行的数据
df.loc[行名]
df.iloc[行下标]

#获取某一列的数据
df.loc[:,列名]
df.iloc[:,列下标]

#获取多行数据
df.loc[[行名1,行名2]]
df.iloc[[行下标1,行下标2]]

#获取多列数据
df.loc[:,[列名1,列名2]]
df.iloc[:,[列下标1,列小标2]]

#使用df[]
#获取行数据,如果m,n为整数,则为左闭右开。如果为行名则,为左闭右闭
df[m:n]
#获取列数据
df[列名或列表]
  • 修改数据与添加数据:都是访问数据的方式后面加“=新值”
  • 删除数据
    df.drop(行名或列表,axis = 0)
    df.drop(列名或列表,axis = 1)
    
    #drop()并不会修改原来的DataFrame,而是返回一个新的DataFrame。列表表示要删除多个列或者行
    

4. 遍历DataFrame的行列

  • 遍历行
    for key,value in df.iterrows():
  • 遍历列
    for key,value in df.iteritems():
import pandas as pd
data = [
    ["小杰","小明","小红"],
    ["男","男","女"],
    [20,19,21]
]

df = pd.DataFrame(data,columns=["name","gender","age"])
for key,value in df.iterrows():
    print(key)
    print(value)
    print("-"*20)
0
name      小杰
gender    小明
age       小红
Name: 0, dtype: object
--------------------
1
name      男
gender    男
age       女
Name: 1, dtype: object
--------------------
2
name      20
gender    19
age       21
Name: 2, dtype: object
--------------------

获取数据

1. 读写JSON

#读取JSON文件,返回一个DataFrame
pd.read_json(path)


#写入JSON文件,是DataFrame的函数并不是pandas库中的函数
df.to_json(path,index = 布尔值,header = 布尔值,force_ascii = 布尔值)
"""
index 可选参数,表示是否输出行名;
     如果想要index = False,则还要设置orient = “split”/"table"
header 可选参数,表示是否输出列名
force_ascii 可选参数,如果JSON中含有中文,则必须有force_ascii = False
"""
import pandas as pd

data = [
    {"学号": 1001, "姓名": "小杰", "性别": "男", "成绩": 650, "班级": "一班"},
    {"学号": 1002, "姓名": "小红", "性别": "女", "成绩": 645, "班级": "一班"},
    {"学号": 1003, "姓名": "小明", "性别": "男", "成绩": 590, "班级": "二班"},
    {"学号": 1004, "姓名": "小华", "性别": "男", "成绩": 640, "班级": "二班"},
    {"学号": 1005, "姓名": "小莉", "性别": "女", "成绩": 635, "班级": "二班"}
]
df = pd.DataFrame(data)
#每行元素用字典表示
# df.to_json(r"data/student_table.json", index=False, orient="table", force_ascii=False)
# print(pd.read_json(r"data/student_table.json"))
#每行的元素用列表表示
df.to_json(r"data/student_split.json",index=False,orient="split",force_ascii=False)
print(pd.read_json(r"data/student_split.json"))
  columns                    data
0      学号  [1001, 小杰, 男, 650, 一班]
1      姓名  [1002, 小红, 女, 645, 一班]
2      性别  [1003, 小明, 男, 590, 二班]
3      成绩  [1004, 小华, 男, 640, 二班]
4      班级  [1005, 小莉, 女, 635, 二班]

2. 读写CSV

```python
#读取csv,返回一个DataFrame对象,是pandas的一个方法
pd.read_csv(path,index_col = m)
# index_col用于将某一列指定为行名,从0开始


#写入csv,是DataFrame的一个方法
df.to_csv(path,index = 布尔值,header = 布尔值)
#index是否输出行名
#header是否输出列名
```
import pandas as pd

#读取csv文件,并将学号即将第一列作为新的行号
df = pd.read_csv(r"data/student.csv",index_col=0)
#输出对齐
pd.set_option("display.unicode.east_asian_width",True)
print(df)
print(type(df))
print("DataFrame的第一行:\n",df.iloc[0])
      姓名 性别  成绩  班级
学号                       
1001  小杰   男   650  一班
1002  小红   女   645  一班
1003  小明   男   590  二班
1004  小华   男   640  二班
1005  小莉   女   635  二班
<class 'pandas.core.frame.DataFrame'>
DataFrame的第一行:
 姓名    小杰
性别      男
成绩     650
班级    一班
Name: 1001, dtype: object

3. 读写Excel

"""
 读取excel:

 1. index_col表示将某一列指定为行名
 2. sheet_name表示选中哪一个表单,默认为0
"""
pd.read_excel(path,index_col = m,sheet_name = n)

"""
写入excel:

 1. index 表示是否输出行名
 2. header 表示是否输出列名
"""
 df.to_excel(path,index = 布尔值, header = 布尔值)

4. 读写HTML

5. 读写数据库

筛选数据

  • 获取行列:loc[]、iloc[]、df[]

  • 重新索引:df.reindex(index=列表, columns=列表)选择某几行或某几列的数据

    • 重新索引与获取行列的区别
      • 当行名或列表不存在时,如果是使用reindex(),那么数据的值就是NaN。
      • 当行名或列表不存在时,如果是使用loc[]、iloc[]、df[],那么程序就会报错。
      • df.reindex(index=列表, columns=列表, fill_value=n)使用fill_value这个参数来将“缺失的数据”填充为“指定值”。
  • 获取首位数据:df.head(n) 和 df.tail(n)使用head()方法来获取前几条数据,使用tail()方法来获取后几条数据。

  • 随机抽样:使用df.sample(n=整数) df.sample(frac=小数)随机抽取一部分数据,n条数据或者frac%的数据

  • 逻辑比较(布尔选择):根据条件选取出数据

    #语法:
      df[条件]
      #条件可以是一个,也可以是多个。df[条件]选取的结果并不是列数据,而是行数据。
    
import pandas as pd
data = [
    ["小杰","男","一班"],
    ["小红","女","一班"],
    ["小明","男","二班"],
    ["小华","男","二班"],
    ["小莉","女","二班"],
]
df = pd.DataFrame(data,columns=["name","gender","class"])

#只有一个条件:选取性别为男的学生
result1 = df[df["gender"] == "男"]
#有多个条件:性别为"男"的二班的学生
result2 = df[(df["gender"] == "男") & (df["class"] == "二班")]
#筛选出除“小杰”以外的数据
result3 = df[df["name"] != "小杰"]


pd.set_option("display.unicode.east_asian_width",True)
print(result1)
print(result2)
print(result3)
   name gender class
0  小杰     男  一班
2  小明     男  二班
3  小华     男  二班
   name gender class
2  小明     男  二班
3  小华     男  二班
   name gender class
1  小红     女  一班
2  小明     男  二班
3  小华     男  二班
4  小莉     女  二班
  • 过滤操作:可以对指定的进行数据过滤

    #相当于SQL中的where语句
    df.query(判断条件)
    
    df.filter(items,like,regex,axis)
    """
    items 是一个列表,表示选取哪些列
    like  是一个字符串,表示对列名进行模糊匹配(类似与SQL中的like)
    regex 一个正则表达式,根据正则表达式来选取列
    
    items\like\regex三个参数是互斥的
    
    axis 是一个可选参数,表示对哪一条轴进行操作
    """
    
import pandas as pd
data = [
    ["小杰",90,100,95],
    ["小红",100,90,90],
    ["小明",95,95,80],
    ["小华",95,90,80],
    ["小莉",95,100,80],
]
df = pd.DataFrame(data,columns=["姓名","语文","数学","英语"])
result1 = df.query("语文<数学")
#等价  result = df[df["语文"]<df["数学"]]
result2 = df.filter(items = ["姓名"])
#等价 result2 = df.filter(like = "姓名")
pd.set_option("display.unicode.east_asian_width",True)
print(result1)
print(result2)
   姓名  语文  数学  英语
0  小杰    90   100    95
4  小莉    95   100    80
   姓名
0  小杰
1  小红
2  小明
3  小华
4  小莉
  • 模式匹配

返回的是布尔值

方法 关系
contains(A) 判断是否包含A
startswith(A) 判断是否以A开头
endwith(A) 判断是否以A结尾
import pandas as pd
data = [
    ["张三","男","前端工程师"],
    ["李红","女","UI设计师"],
    ["王莉","女","平面设计师"],
    ["张杰","男","后端工程师"],
    ["王红","女","室内设计师"]
]

df = pd.DataFrame(data,columns=["name","gender","job"])

#返回一组布尔值
bools = df["job"].str.contains("工程师")
#将这些布尔值放到df[]中作为“布尔索引”,从而将对应的行选取出来
result = df[bools]

pd.set_option("display.unicode.east_asian_width",True)
print(result)
   name gender         job
0  张三     男  前端工程师
3  张杰     男  后端工程师

处理数据

1. 操作行名和列名

  • 设置某一列为行名
      df.set_index(列名,drop = 布尔值)
    
      #drop为可选参数,表示是否舍弃原来的列
      #返回一个新的DataFrame,而不是修改原来的DataFrame
    
  • 重置行名
      df.reset_index(drop = 布尔值)
    
      #drop为可选参数,表示是否舍弃原来的列
      #返回一个新的DataFrame,而不是修改原来的DataFrame
    
  • 修改行名和列名
      df.index = 列表
      df.columns = 列表
    
    
      df.rename(index = 字典,columns = 字典)
      #使用rename来修改行名和列名,index和columns是可选参数,字典的键是原来的名字,字典的值是修改后的名字
      #rename()返回一个新的DataFrame
    
import pandas as pd
data = [
    [1001,"小杰","男",650,"一班"],
    [1002,"小红","女",645,"一班"],
    [1003,"小明","男",590,"二班"],
    [1004,"小华","男",640,"二班"],
    [1005,"小莉","女",635,"二班"]
]

df = pd.DataFrame(data,columns=["学号","姓名","性别","成绩","班级"])
pd.set_option("display.unicode.east_asian_width",True)
print("原二维数据表:\n",df)

#删除序号为1和4行,并重置行名
df1 = df.drop([1,4],axis = 0)
result2 = df1.reset_index(drop = True)
print("重置行名,不保留原来的行名:\n",result2)

#修改列名
result2.columns = ["std","name","gender","grade","class"]
print(result2)
#修改行名
result3_1 = result2.rename(index = {0:"first",1:"second",2:"third"})
print("修改行名\n",result3_1)
原二维数据表:
    学号  姓名 性别  成绩  班级
0  1001  小杰   男   650  一班
1  1002  小红   女   645  一班
2  1003  小明   男   590  二班
3  1004  小华   男   640  二班
4  1005  小莉   女   635  二班
重置行名,不保留原来的行名:
    学号  姓名 性别  成绩  班级
0  1001  小杰   男   650  一班
1  1003  小明   男   590  二班
2  1004  小华   男   640  二班
    std  name gender  grade class
0  1001  小杰     男    650  一班
1  1003  小明     男    590  二班
2  1004  小华     男    640  二班
修改行名
          std  name gender  grade class
first   1001  小杰     男    650  一班
second  1003  小明     男    590  二班
third   1004  小华     男    640  二班

2. 类型转换

  • DataFrame转换成其他类型
    • DataFrame to dictionary
          df.to_dict(into = 值)
          #默认为dict,一般为默认值
    
    • DataFrame to numpy
      np.array(df)
      
    • DataFrame to list:要先将DataFrame转换为数组,再将数组转换为列表
      df_array = np.array(df)
      df_list = df_array.tolist()
      
  • 针对某一列转换成其他类型
      df[列名].astype(类型)
      #astype()的参数取值:int\float\str等
      #astype()并不会修改原来的列(Series)而是会返回一个新的列(Series)
    
import pandas as pd
import numpy as np
data = [
    ["苹果",6.4,"秋季"],
    ["西瓜",2.5,"夏季"],
    ["香蕉",7.8,"四季"],
    ["李子",12.4,"夏秋"],
    ["芒果",3.5,"夏季"]
]
df = pd.DataFrame(data,columns=["fruit","price","season"])

#将df转换为dict
result1 = df.to_dict()
#将df转换为数组
result2 = np.array(df)
#将df先转换为数组,再讲数组转换为列表
result3 = result2.tolist()

pd.set_option("display.unicode.east_asian_width",True)
print(result1)
print(result2)
print(result3)

#将price列的类型转换为int型
df['price'] = df["price"].astype(int)
print(df)
{'fruit': {0: '苹果', 1: '西瓜', 2: '香蕉', 3: '李子', 4: '芒果'}, 'price': {0: 6.4, 1: 2.5, 2: 7.8, 3: 12.4, 4: 3.5}, 'season': {0: '秋季', 1: '夏季', 2: '四季', 3: '夏秋', 4: '夏季'}}
[['苹果' 6.4 '秋季']
 ['西瓜' 2.5 '夏季']
 ['香蕉' 7.8 '四季']
 ['李子' 12.4 '夏秋']
 ['芒果' 3.5 '夏季']]
[['苹果', 6.4, '秋季'], ['西瓜', 2.5, '夏季'], ['香蕉', 7.8, '四季'], ['李子', 12.4, '夏秋'], ['芒果', 3.5, '夏季']]
  fruit  price season
0  苹果      6   秋季
1  西瓜      2   夏季
2  香蕉      7   四季
3  李子     12   夏秋
4  芒果      3   夏季

3. 行列转置:T

#语法:df.T,返回一个新的DataFrame
#应用
result = df.T

4. 大小排序:sort_values()

```python
df.sort_values(by = 列表,ascending = 布尔值)
# by 表示需要进行排序的列名
# ascending 可以是一个布尔值列表
```

5. 数据排名:rank()

数据排名和大小排序类似,区别在于数据排名会新增一个列,用于表示排名的情况

 df[列名].rank(ascending = 布尔值,method = 值)
 #method = average(默认)/max/min/first(according to the squence of old data)

6. 数据替换:replace()

   #替换一个值
   df.replace(A,B)

   #替换多个值
   df.replace(字典)

7. 数据移动:shift()

   df.shift(n,axis = 0或1)

   #n是一个可选参数,表示移动的步数,默认值为1。可以为正也可以为负
   # 移动的是数据部分,行名部分不移动,若移动后行名没有对应的数据,那么空数据将被赋值为NaN

   df[列名].shift(n)
   #表示只对某一列进行移动

8. 数据清洗

脏数据:存在数据缺失、数据重复、数据异常等问题的数据
数据清洗指的是对这些“脏数据”进行处理,为后面数据分析做准备。

  • 判断缺失值:df.isnull()

    #用布尔选择把包含缺失值的行选择出来
    
    result = df[df.isnull().values == True]
    
  • 处理缺失值:
    ①删除包含缺失值的行或列

       df.dropna(axis = 0或1,how = "any"或"all")
       
       #how是一个可选参数,表示删除的规则,默认值为any
       #any表示这一行或这一列只要有一个缺失值就删除这一行或这一列;all表示全部缺失才删除。
    

    ②填充

       df.fillna(value = 字典,method = 填充方式)
    
       #value、method都是可选参数,
       #value 是一个字典,字典的键表示列名,字典的值对应填充值
       #method = ffill/bfill,ffill是使用前值填充,bfill是使用后值填充
    
  • 重复值
    1.判断是否有重复值:df.duplicated()
    2. 处理重复值:
    df.drop_duplicates(subset = 列表,keep = 值) 用来删除重复数据
    只能对行进行操作不能对列进行操作

    如果要对列进行处理,则先转置再删除重复值再转置
    df.T.drop_duplicates().T

    subset 可选参数 对指定的列进行重复值判断。如果省略subset则会对所有列进行判断

    keep = frist/last/False 保留第一次出现的重复行、保留最后一次出现的重复行、删除所有重复行

  • 异常值

    1. 判断异常值
    2. 处理异常值:删除该行或列、填充

9. 数据合并

  • concat():轴向合并,即“沿着某一条轴”合并两个数据集

data1.append(data2) 将data2加入到data1形成新的列表

   pd.concat(列表,axis=0或1,join = 连接方式,ignore_index = 布尔值)

   #join是一个可选参数,join = outer/inner
   #ignore_index 是否忽略原来的行名并重置行名

a. 纵向合并,有重复值

   pd.concat([df1,df2],axis = 0)
   """
   步骤:1.合并数据2.去重处理3.重置行名
   result = pd.concat([df1,df2],axis = 0)
   result = result.drop_duplicates(subset["fruit","price","season"])
   result = result.reindex(drop = True)
   """

b.横向合并,去除重复列

   #步骤:1. 合并数据 2.去重处理
   result = pd.concat([df1,df2],axis = 1)
   result = result.T.drop_duplicates().T
  • merge():主键合并,"根据一个或多个键"来合并不同该数据集。主键合并这种方式,一般情况下是将两个DataFrame中相同的列作为合并的键。
   pd.merge(df1,df2,how = "连接方式")

   """
   innder(默认值): 内连接(求交集)
   outer:          外连接(求并集)
   left:           左连接
   right:          右连接
   """
  • join():行列连接,根据指定的行或列合并两个数据集
   df1.join(df2,on = 行名或列名)
import pandas as pd
data1 = [
    ["苹果",6.4,"秋季"],
    ["西瓜",2.5,"夏季"],
    ["芒果",3.5,"夏季"]
]
data2 = [
    [100,"A"],
    [200,"B"]
]

df1 = pd.DataFrame(data1,columns=["fruit","price","season"])
df2 = pd.DataFrame(data2,index = ["夏季","秋季"],columns=["sales","level"])

#合并数据
result = df1.join(df2,on = "season")

pd.set_option("display.unicode.east_asian_width",True)
print(result)


"""
df2的行名["夏季","秋季"],和df1中“season”这一列有重叠,这里会将df2的数据映射到df1中,返回映射后的结果
"""
  fruit  price season  sales level
0  苹果    6.4   秋季    200     B
1  西瓜    2.5   夏季    100     A
2  芒果    3.5   夏季    100     A
  • append():纵向合并
   df1.append(df2,ignore_index = 布尔值)

10. 字符串处理

```python
#语法
Series.str.方法名()
```

11. 自定义函数

  • map():应用于一列

    df[].map(fn)

    fn既可以是一个函数名,也可以是一个lambda表达式

  • apply():应用于多列

    df[].apply(fn,args = 元组)

    args是一个可选参数,它的值是一个元组。如果

    args参数存在,那么它的值就会参与到fn的计算中去

  • applymap():应用于整个DataFrame
    df.applymap(fn)

分析数据

image.png

#语法:df.函数()

image.png

3. 整体情况

  1. df.describe()-一次性获取一个DataFrame的多个统计值,包括个数、中位数、标准差、最大值、最小值

describe()只对数字类型的列进行统计

  1. df.info()-获取一个数据集的基本信息,包括类型、列名、个数、内存

4. 聚合函数:agg()-可以同时应用多个统计函数

   df.agg(列表)
   # 列表的元素是统计函数名,例如sum、max、min、mean等

5. 数据分组

  1. groupby()
```python
    df.groupby(列名或列表)
    #参数是“列名”时,表示根据一列进行分组
    #当参数是列表时,表示根据多列进行分组
    # 返回一个DataFrameGroupby对象,该对象是一个可迭代对象for name,group in result, name是组名,group是数据
```
  1. get_group()-根据“组名”获取某一组的数据
```python
    分组对象.get_group(组名)
    #get_group()是分组对象下的一个方法,它接受一个组名作为参数
    #如果同时对多列进行分组,那么使用get_group()获取某一组的数据时,它接收的是一个元组
```
  1. 统计分析:分组对象同样可以使用 统计函数 及 聚合方法
posted @ 2024-08-12 21:20  枫木流云  阅读(53)  评论(0)    收藏  举报