数据分析工具Pandas

Pandas是一个强大的分析和操作大型结构化数据集所需的工具集
基础是Numpy,提供了高性能矩阵的运算
提供了大量能够快速便捷地处理处理数据的函数和方法
应用于数据挖掘,数据分析,提供数据清洗功能

一、Pandas的数据结构

导入pandas:

import pandas as pd
from pandas import Series, DataFrame
import numpy as np
import matplotlib.pyplot as plt

1、Series

series是一种类似于一维数组的对象,由一组数据和与之对应的索引组成。
索引(index)在左,数据(values)在右,索引是自动创建的

(1)series的创建
 特别地,由ndarray创建的是引用,而不是副本,对Series元素的改变也会改变原来的 ndarray对象中的元素。

# 1、通过list或者numpy数组创建

# 默认索引为0-N-1的整数型索引
s = Series(np)
# 可以通过设置index参数指定索引
s.index = list("abcde") 

s2 = Series(range(10, 30))

# 2、通过dict构建

s3 = Series({1000: "hello", 2000: "world", 3000: "!"})

(2)Series的索引和切片

可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的仍是Series类型)。

# 显式索引:使用index中的元素作为索引值 / 使用.loc[]
# 注意此时是闭区间

s = Series(np.random.random(7), index = list("abcdefg"))
print(s)
s.loc["a"]

# 隐式索引:使用整数作为索引值 / 使用.iloc[]
# 注意此时是半开区间
s.iloc[0]

# 进行切片
s.loc["a": "c"]

(3)Series的基本概念

可以把series看成一个定长的有序字典
可以通过shape,size,index,values等得到series的属性

display(s.shape, s.size, s.index, s.values)

# 可以通过head(), tail()快速查看Series对象的样式
s.head(3) # 打印前三行
s.tail(3) # 打印后三行

# 当索引没有对应的值时,可能出现去缺失数据显示NaN的情况
s = Series([1, 26, None, np.nan], index=list("风火雷电"))

# 可以使用pd.isnull(), pd.notnull()来检测缺失数据
s1 = s.notnull()
# 获取不为空的数据
s[s1]

# Series对象本身及其实力都有一个name属性
# 对于dataFrame来说,name就是列名

(4)Series的运算

在运算中自动对齐不同索引的数据
如果索引不对应,则补NaN

s1 = Series([2, 4, 7 ,9], index=[0, 1, 2, 3])
s2 = Series([1, 2, 3, 4], index=[2, 3, 4, 5])
# 在进行相加时,索引相同的进行相加
s1+s2 

# 如果想要保留所有的index,需要使用.add()函数
s1.add(s2, fill_value=0)

2、DataFrame

是一个表格型的数据结构,可以看做是由series组成的字典,由按一定顺序排列的多列数据组成。既有行索引(自动创建),也有列索引。
行索引:index 列索引:columns 值:values

最常用的方法是传递一个字典来创建。以字典的键作为每一列的名称,以字典的值作为每一列。 此外,DataFrame会自动加上每一行的索引(和Series一样, 若传入的列与字典的键不匹配,相应的值为NaN。

(1)创建DataFrame

# 通过ndarray构建DataFrame
arr_obj = np.random.rand(3, 4)
df_obj = DataFrame(arr_obj)

# 通过dict构建DataFrame
df = DataFrame(
{
		"height": [175, 180, 169, 188],
		"age": np.random.randint(18, 25, size=4),
		"sex": ["男", "女", "男", "女"],
		"weight": [60, 50, 77, 80]
	},
	index=list("ABCD"),
	columns=["height", "age", "sex", "weight"]
	)

(2)DataFrame的索引

# 1、对列进行索引

# - 通过类似字典的方式
# 检索列的返回值时Series
age = df["age"]
display(type(age))

# - 通过属性的方式
# 对于DataFrame而言,列就相当于属性
df.age 

# 2、对行进行索引

# - 使用.loc[]加 index来进行行索引
# 对于行的检索,返回值也是Series
df.loc["A"]
# 如果检索多行返回的数据就是DataFrame
df.loc[["A", "B"]]
# 切片是行切片
df.loc["A": "C"]

# - 使用.iloc[]加整数来进行行索引,左闭右开
df.iloc[1: 3]

# 检索行的时候,参数可以是多个,但是列不行
df.loc[["sex", "B"]]

(3)DataFrame的运算
  同Series一样:
    在运算中自动对齐不同索引的数据
    如果索引不对应,则补NaN

# 创建月考一不同人员的各科目成绩
df1 = DataFrame(np.random.randint(0, 150, size=(4, 4)),
							index=["张三", "李四", "王五", "赵六"],
							columns=["语文", "数学", "英语", "Python"])

# 月考二,有新学生转入
df2 = DataFrame(np.random.randint(0, 150, size=(5, 3)),
							index=["张三", "李四", "王五", "赵六", "田七"],
							columns=["语文", "数学", "英语"])
df1 + df2
# 加和的结果
df1.add(df2, fill_value=0)

(4)Series与DataFrame之间的运算
【重要】
  使用python操作符:以行为单位操作(参数必须是行),对所有行都有效。类似于Numpy中二维数组于一维数组的运算,但可能出现NaN。
 使用pandas操作函数,如add():
  axis=0:以列为单位操作(参数必须是列),对所有列是有效。
  axis=1:以行为单位操作(参数必须是行),对所有行都有效。

s1 = df1["Python"]
df1 + s1   # 索引不同,所得的数据均为NaN

ss = df1["Python"] # 此时是列索引,对所有行操作,所以参数为行
df1.add(ss, axis=0) 

ss2 = df1.loc["张三"] # 此时是行索引,对所有列操作
df1.add(ss2, axis=1)

在这里插入图片描述

二、Pandas层级索引

1、隐式构造
最常见的方法是给DataFrame构造函数的index参数传递两个或更多的数组
series也可以创建多层索引

# Series
s = Series([1, 2, 3, 4], index=[["a", "a", "b", "b"], [0, 0, 1, 1]])

# DataFrame
df = DataFrame(np.random.randint(0, 150, size=(6, 3)),
              columns=["语文", "数学", "Python"],
              index=[["Michael", "Michael", "Lisa", "Lisa", "PO", "PO"], ["middle", "end", "middle", "end", "middle", "end"]])

2、显式构造

(1)使用数组

df1 = DataFrame(np.random.randint(0, 150, size=(6, 3)),
               columns=["Java", "Html5", "Python"],
               index=pd.MultiIndex.from_arrays([["张三", "张三", "李四", "李四", "王五", "王五"], ["期中", "期末", "期中", "期末", "期中", "期末"]])
               )
df1

(2)使用元组

df2 = DataFrame(np.random.randint(0, 150, size=(6, 3)), 
               columns=["Java", "Html5", "Python"],
               index=pd.MultiIndex.from_tuples([("张三", "期中"), ("张三", "期末"),("李四", "期中"), ("李四", "期末"), ("王五", "期中"), ("王五", "期末")])
               )
df2

(3)使用product,最简单

df3 =  DataFrame(np.random.randint(0, 150, size=(6, 3)), 
               columns=["Java", "Html5", "Python"],
               index=pd.MultiIndex.from_product([["张三", "李四", "王五"], ["期中", "期末"]])
               )
df3

(4)DataFrame列同样可以设置多层索引

df4 = DataFrame(
    np.random.randint(0, 150, size=(3, 6)),
    columns = pd.MultiIndex.from_product([["Java", "Html", "Python"], ["期中", "期末"]]),
    index = ["张三", "李四", "王五"]
)
df4

三、多索引对象的索引与切片操作

1、Series的操作

【重要】对于Series来说,直接中括号[]和.loc完全一样,因此,推荐使用中括号索引和切片

# 索引
s = Series([1, 2, 3, 4], index=[["a", "a", "b", "b"], [0, 1, 0, 1]])
s

s["a", 0] # 第一个参数,多层索引的第一维,第二个参数是第二维

s[["a", "期中"]] # 其实此时只有一个参数

# 切片
s["a": "b"]
s.iloc[0: 3]

2、DataFrame的操作

可以直接使用列名称来进行列索引
使用行索引需要使用loc()函数

【注意】在对行索引的时候,若一级索引还有多个,对二级索引会遇到问题,也就是 无法直接对二级索引进行索引,必须等到让二级索引变成一级索引后才能对其进行索引

df1["张三" : "李四"]

# df1["张三", "期中"] # 报错
df1.loc["张三", "期中"]

# df1.loc["张三"]["期中"] 报错
df1.loc["张三"].loc["期中"]

四、索引的堆

【技巧】使用stack()的时候,level等于哪一个,哪一个就消失,出现在行里
使用unstack()的时候,level等于哪一个,那一个就消失,出现在列里

df4.stack(level=0)

在这里插入图片描述

df2.unstack(level=1)

在这里插入图片描述

五、Pandas的拼接操作

级联:pd.concat,pd.append
合并:pd.merge, pd.join

# 生成2个3*3的矩阵,对其分别进行两个维度上的级联
nd1 = np.random.randint(0, 10, size=(3, 3))
nd2 = np.random.randint(0, 10, size=(3, 3))
np.concatenate((nd1, nd2), axis=0) # 0是第一维的方向:行

1、简单级联
和np.concatenate一样,优先增加行数(默认axis=0)

df1 = DataFrame(np.random.randint(1, 10,size=(2, 2)),
               index=[0, 1],
               columns=["A", "B"])

df2 = DataFrame(np.random.randint(1, 10, size=(2, 2)),
               index=[2, 3],
               columns=["A", "B"])

pd.concat([df1, df2])

# 注意index在级联时可以重复
df3 = DataFrame(np.random.randint(1, 10, size=(3, 2)),
               index=[0, 1, 2],
               columns=["A", "B"])
df4 = pd.concat([df1, df3])
df4

# 也可以选择忽略ignore_index,重新索引
pd.concat([df1, df3], ignore_index=True)

# 或者使用多层索引keys
pd.concat([df1, df3], keys=["x", "y"])

2、不匹配级联

不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致。
(1)外连接:补NaN(默认方式)

df1 = DataFrame(np.random.randint(1, 10, size=(2, 2)),
                index=[1, 3],
                columns=["A", "B"])
                
df2 = DataFrame(np.random.randint(1, 10, size=(2, 2)),
               index=[2, 4],
               columns=["B", "C"])
 
 pd.concat([df1, df2], join="outer")

(2)内连接:只连接匹配的项

pd.concat([df1, df2], join="inner")

# 连接指定轴join_axes,以某一个DataFrame的列索引为新的列索引值
df3 = DataFrame(np.random.randint(1, 10, size=(3, 3)),
               index=[0, 1, 2],
               columns=["A", "C", "D"])
               
df4 = DataFrame(np.random.randint(1, 10, size=(3, 3)),
               index=[3, 4, 5],
               columns=["C", "D", "F"])

pd.concat([df3, df4], join_axes=[df3.columns])

(3)使用apppend()函数添加

由于在后面级联的使用非常普遍,因此有一个函数append专门用与在后面添加

df1 = DataFrame(np.random.randint(1, 10, size=(5, 2)),
               index=[0, 1, 2, 3, 4],
               columns=["大众", "福克斯"])

df2 = DataFrame(np.random.randint(1, 10, size=(5, 2)),
               index=[5, 6, 7, 8, 9],
               columns=["大众", "福克斯"])
df1.append(df2)

3、merge合并

merge与concat的区别在于,merge需要依赖某一共同的行或列来进行合并。
使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来合并。

(1)一对一合并

df1 = DataFrame({"employee": ["Po", "Sara", "Danis"],
                 "group": ["sail", "counting", "marketing"]})
                 
df2 = DataFrame({"employee": ["Po", "Sara", "Dansi"],
                 "work_time": [2, 3, 1]})
display(df1, df2)

pd.merge(df1, df2)

(2)多对一合并

df1 = DataFrame({"employee": ["Po", "Sara", "Danis"],
                 "group": ["sail", "counting", "marketing"]})
                 
df2 = DataFrame({"employee": ["Po", "Po", "Dansi"],
                 "work_time": [2, 3, 1]}) 
display(df1, df2)

pd.merge(df1, df2)

(3)多对多合并

df1 = DataFrame({"employee": ["Po", "Po", "Danis"],
                 "group": ["sail", "counting", "marketing"]})
                 
df2 = DataFrame({"employee": ["Po", "Po", "Dansi"],
                 "work_time": [2, 3, 1]}) 
display(df1, df2)

pd.merge(df1, df2) # 在进行多对多合并时,每一个数据都没有放过

4、key的规范化

使用on=显式指定哪一列为key,当有多个key相同时使用

df3 = DataFrame({"employer": ["Po", "Summer", "Flower"],
                "group": ["sail", "marketing", "serch"],
                "salary": [12000, 10000, 8000]})
                
df4 = DataFrame({"employee": ["Po", "winter", "Flower"],
                "group": ["sail", "marketing", "serch"],
                "work_time": [2, 1, 5]})
display(df3, df4)

pd.merge(df3, df4, on='employee')

pd.merge(df3, df4, on='group', suffixes=["_a", "_b"]) 

使用left_on和right_on指定左右两边的列作为key,当左右两边的key都不相等时使用

pd.merge(df3, df4, left_on="employer", right_on="employee")

5、内合并与外合并

内合并:只保留两者都有的key(默认模式)
外合并:全部保留

df1 = DataFrame({"age": [18, 22, 33], "height": [175, 169, 180]})
df2 = DataFrame({"age": [18, 23, 31], "weight": [65, 70, 80]})
display(df1, df2)

pd.merge(df1, df2, how="outer")
pd.merge(df1, df2, how="inner")

pd.merge(df1, df2, how="left") # 左合并
pd.merge(df1, df2, how="right") # 右合并

六、Pandas数据处理

1、删除重复元素

使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现则元素为True

df = DataFrame(np.random.randint(0, 3, size=(6, 2)),
              index=["张三", "李四", "王五", "李四", "小吴", "张三"],
              columns=["语文", "数学"])

# 检查重复元素
df.duplicated()

# 使用duplicates()函数删除重复的行 ,列名不能重复,否则操作会报错
df.drop_duplicates()

# 如果使用pd.concat([df1, df2], axis=1) 生成新的DataFrame,新的df中columns相同,使用duplicate和drop_duplicates都会出现问题

2、数据的映射

创建一个映射关系列表,把values元素和一个特定的标签或者字符串绑定

df = DataFrame(np.random.randint(10, 100,size=(3, 3)),
              index=["张三", "李四", "王五"],
              columns=["Python", "Java", "UI"])

df["Python"] = df["Python"].map(lambda x: x+10)

# map()不仅可以根据条件修改当前列,还可以映射新一列数据,我们可以在map()
# 中使用lambda表达式,还可以使用方法,可以自己实现的方法
df["Html"] = df["Java"].map(lambda x: x+3)

3、reanme()函数:替换索引

仍然是新建一个字典

index = {"张三": "zhangSir", "李四": "liSir"}
df.rename(index=index)

4、异常值检测和过滤

使用describe()函数查看每一列的描述性统计量

df = DataFrame(np.random.randint(0, 150, size=(6, 3)),
              index=list("ABCDEF"),
               columns=list("语数外"))

df.describe() # std()标准方差

5、使用.take()函数排序

可以借助np.random.permutation()函数随机排序

per = np.random.permutation(6)
df.take(per)

6、数据聚合

数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。
数据分类处理:
分组:先把数据分为几组
用函数处理:为不同组的数据应用不同的函数以转换数据
合并:把不同组得到的结果合并起来
数据分类处理的核心:groupby()函数

df = DataFrame({"item": ["苹果", "香蕉", "橘子", "香蕉", "橘子", "苹果"],
               "price": [4, 3, 3, 2, 4, 2],
               "color": ["red", "yellow", "yellow", "green", "red", "green"]})

g = df.groupby("item")
g.groups

g["price"].mean() # 求平均值

df = DataFrame({
                "item": ["萝卜", "白菜", "辣椒", "冬瓜", "白菜", "辣椒", "冬瓜", "白菜"],
               "color": ["red", "red", "green", "green", "white", "green", "white", "white"],
                "weight": np.random.randint(50, 150, size=8),
               "price": np.random.randint(1, 4, size=8)
               })

# 对df进行聚合操作,求出颜色为白色的价格总和
g = df.groupby("color")["price"]
g.sum()
g.sum()["white"]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值