数据分析--03:Pandas

데이터 분석--03: 팬더

一、Pandas介绍与安装

1、为什么会有Pandas?

  • Pandas支持大部分Numpy语言风格,尤其是数组函数与广播机制的各种数据处理。但是Numpy更适合处理同质型的数据。而Pandas的设计就是用来处理表格型或异质型数据的,高效的清洗、处理数据。

2、Pandas是什么?

  • Pandas是基于Numpy的一种工具,提供了高性能矩阵运算,该工具是为了解决数据分析任务而创建的。也是贯穿整个Python数据分析非常核心的工具。

3、Pandas涉及内容

请添加图片描述

4、Pandas的安装

  • windows
    • 直接在dos命令中执行pip install pandas
  • macOS
    • 在terminal运行终端内执行pip3 install pandas

二、Pandas基础数据结构

1、Series

1.Series介绍

  • Series是一种一维的数组型对象,它包含了一个值序列(values),并且包含了数据标签,称为索引(index)。

2.Series的创建

  • pd.Series(data=None,index=None,dtype=None,name=None,copy=False)
    • data:创建数组的数据,可为array-like, dict, or scalar value
    • index:指定索引
    • dtype:数组数据类型
    • name:数组名称
    • copy:是否拷贝

data可为iterable, dict, or scalar value

import pandas as pd
import numpy as np


a1 = np.array([1, 2, 3])
print(a1)
print(type(a1))

# Series数据结构
## 1、创建方式
### 1.通过列表创建
p1 = pd.Series([1, 2, 3, 4, 5])
print(p1)
print(type(p1))

# 索引属性(整型索引序列  默认从0开始,步长为1)
print(p1.index)

# 值(值就是数组)
print(p1.values)
print(type(p1.values))

# 值的数据类型
print(p1.dtype)

### 2.通过元组创建Series
p2 = pd.Series((1, 2, 3, 4, 5))
print(p2)

### 3.通过数组创建Series
p3 = pd.Series(a1)
print(p3)

# 修改索引值
p4 = pd.Series(a1, index=['a', 'b', 'c'])
print(p4)

### 4.通过字典创建Series
d = {'name':'王佳欣', 'sex':'男', 'age':24}
p5 = pd.Series(d)
print(p5)
# 当对象指定索引之后,就不能重新指定索引
p6 = pd.Series(d, index=['a', 'b', 'c'])
print(p6)

索引默认为range(0,n) 可以通过index指定索引
import pandas as pd
pd.Series([1,2,3,4,5],index=list("abcde"))
数据类型根据data自动调整,但是也可以通过dtype指定
import pandas as pd
pd.Series(np.random.randint(1,10,size=5),dtype="float")
使用name参数设置数组名称
import pandas as pd
pd.Series(np.random.randint(1,10,size=3),index=list("abc"),name="data_name")

除此之外,Pandas可以使用Numpy的数组函数

  • s.dtype # 查看数据类型
  • s.astype() # 修改数据类型
  • s.head(n) # 预览数据前5条
  • s.tail(n) # 预览数据后5条

但是如果需要显示所有数据,则需要以下代码。但不建议使用

#显示所有列
pd.set_option('display.max_columns', None)

#显示所有行
pd.set_option('display.max_rows', None)

#设置value的显示长度为100,默认为50
pd.set_option('max_colwidth',100)

3.Series的索引与值

  • s.index # 查看索引
  • s.values # 查看值序列
  • s.reset_index(drop=False) # 重置索引
    • drop # 是否删除原索引 默认为否
      注意:索引对象是不可变的,所以不能单个修改索引
import pandas as pd
p1 = pd.Series([1, 2, 3, 4, 5])
print(p1.index)
print(p1.values)
print(type(p1.values))

4.Series索引与切片

  • s['标签'] # 通过标签
  • s['索引'] # 通过索引
  • s.loc(标签) # 通过标签
  • s.iloc(索引) # 通过索引
import numpy as np
import pandas  as pd


d = {'name':'王佳欣', 'sex':'男', 'age':24, 'class':'一体化二班'}
p1 = pd.Series(d)
# print(p1.index)


# 1、位置索引
print(p1[0])

# 2、标签名索引(类似于字典键值对取值)
print(p1['name'])

# 选择多个数据
print(p1[[0, 2]])
print(p1[['name', 'sex']])


# 3、下标切片(不包含末端数据)
print(p1[1:3])


# 4、标签切片(包含末端数据)
print(p1['age':'class'])


# 5、布尔索引
a1 = np.array([1, 2, 3])
p2 = pd.Series(a1, index=['a', 'b', 'c'])
print(p2>2)
print(p2[p2>2])


# 6、数组的广播(索引与数据对应关系不会被运算结果影像)
print(p2+3)
p2.name = '人数' # 对象名
p2.index.name = '班级' # 索引对象名
print(p2)

5.Series运算

  • 共同索引对应为运算,其他填充NaN
import pandas as pd


s1 = pd.Series(range(10,20),index=range(10))

s2 = pd.Series(range(20,25),index=range(5))

s1+s2 
  • 没有共同索引时,则全部为NaN

2、DataFrame

1.DataFrame介绍

  • DataFrame表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值,字符串,布尔值)。在DataFrame中,数据被存储为一个以上的二维块。

请添加图片描述

2.DataFrame的创建

  • pd.DataFrame(data=None,index=None,columns=None,dtype=None,copy=False)
    • data:创建数组的数据,可为ndarray, dict
    • index:指定索引
    • dtype:数组数据类型
    • copy:是否拷贝
import pandas as pd
import numpy as np


# DataFrame(表格形式数据结构)
# 创建方式
## 1.字典类创建
data = {
    'A': [1, 2, 3],
    'B': (4, 5, 6),
    'C': np.arange(7, 10)
}
p1 = pd.DataFrame(data)
print(p1)
print(type(p1))

# index  行索引
print(p1.index)

# columns 列索引
print(p1.columns)

# 获取值
print(p1.values)


p = pd.DataFrame(data, index=['a', 'b', 'c'])
print(p)



## 2.series对象来创建
p2 = pd.DataFrame({
    'a': pd.Series(np.arange(3)),
    'b': pd.Series(np.arange(3, 5))
                   })
print(p2)



## 3.字典类创建
data1 = {
    'a':{'apple': 3.6, 'banana': 5.6},
    'b':{'apple': 3, 'banana': 5},
    'c':{'apple':3.2}
}
p3 = pd.DataFrame(data1)
print(p3)


## 4.列表类创建
arr = np.arange(12).reshape(3, 4)
p4 = pd.DataFrame(arr, index=['a', 'b', 'c'], columns=['A', 'B', 'C', 'D'])
print(p4)


## 5.字典构造列表,构造DataFrame
list1 = [{'apple': 3.6, 'banana': 5.6},{'apple':3, 'banana':5},{'apple': 3.2}]
p5 = pd.DataFrame(list1)
p5.index.name = '次数'
p5.columns.name = '水果'
print(p5)


## 6.Series组成的列表构造DataFrame
list2 = [pd.Series(np.arange(3)), pd.Series(np.arange(3, 6))]
p6 = pd.DataFrame(list2)
print(p6)

3.重置索引

  • 除了创建时可以指定,我们创建后还可以通过df.reindex()进行重制索引。
    • df.reindex(index=None, columns=None, axis=None,fill_value=nan)

4.DataFrame基础操作

  • df.shape # 查看数组形状,返回值为元组
  • df.dtypes # 查看列数据类型
  • df.ndim # 数据维度,返回为整数
  • df.index # 行索引
  • df.columns # 列索引
  • df.values # 值
  • d.head(n) # 显示头部几行,默认前5行
  • d.tail(n) # 显示末尾几行,默认后5行
  • d.info() # 相关信息概述
import pandas as pd
import numpy as bp
data = [
    {"name":"amy","age":18,"tel":10086},
    {"name":"bob","age":18},
    {"name":"james","tel":10086},
    {"name":"zs","tel":10086},
    {"name":"james","tel":10086},
    {"name":"ls","tel":10086},
]

d2 = pd.DataFrame(data)
d2.head()  
d2.tail()  
d2.info() 

5.DataFrame查数据

  • 直接使用索引与标签
类型描述
df[索引]或df['标签’]表示对行操作
df[“列标签”]或 df[[“列标签”,“列标签”]]表示对列进行操作
import numpy as np
import pandas as pd


# 索引
p1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
print(p1)

#1.查a列(必须先列后行)
print(p1['a'])
print(p1['a']['A'])

练习一

  • 读取文件catNames2.csv
    • 取前两行
    • 取出Count_AnimalName列
    • 取出Row_Labels前两行
      练习二
  • 找到所有的使用此时超过800的猫的名字
使用loc及iloc查询数据:
  • df.loc[] 通过轴标签选择数据
  • df.iloc[] 通过整数索引选择数据

具体使用如下:

类型描述
df.loc[val]根据标签索引选择DataFrame的单行或多行
df.loc[:,val]根据标签索引选择DataFrame的单列或多列
df.loc[val1,val2]同时选择行和列中的一部分
df.iloc[where]根据位置索引选择DataFrame的单行或多行
df.iloc[:,where]根据位置索引选择DataFrame的单列或多列
df.iloc[where_i,where_j]根据位置索引选择行和列
import numpy as np
import pandas as pd


# 索引
p1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
print(p1)
# 2.高级索引操作
print(p1.loc['A'])
print(p1.loc['A']['a'])

6.DataFrame修改数据

  • 修改数据主要遵循以下两点:
    • 查询数据
    • 再赋值
import numpy as np
import pandas as pd


# 索引
p1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
print(p1)

# 3.修改数组
p1['a'] = 7
print(p1)
p1.loc['A'] = 0
print(p1)

注意:Pandas中可以直接赋值np.nan,且赋值当前列数据会自动转为浮点类型。而不是整个数组都转,这主要是因为Pandas数据可以是异质性。

7.DataFrame新增数据

新增列df["新的列标签"] = 值
注意:添加列,则新添加的值的长度必须与其它列的长度保持一致,否则会报错。
插入列:如果需要在数据中插入列,则使用 df.insert(loc, column, value)

  • loc 为插入列的位置
  • column 为插入列的标签
  • value 为插入列的值

添加行:df.loc[“新的行标签”,:] = 值

除此之外,我们还可以通过 df.append(df2) 方法添加行,但类似于数组与数组的堆叠拼接。所以df2的列索引必须同df一致。

import numpy as np
import pandas as pd


# 索引
p1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
print(p1)

# 增加数据
p1['A'] = 9
# print(p1)
p1.loc['d'] = 0
print(p1)

8.DataFrame删除数据

法1:del df[“列标签”]
法2:df.drop(axis=0,index=None,columns=None, inplace=False)

import numpy as np
import pandas as pd


# 索引
p1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
print(p1)

# 删除数据
del(p1['A'])
print(p1)

p1.drop('d', axis=0, inplace=True) # 删除行     inplace=True相当于在原数据上修改
print(p1)

9.DataFrame算数

  • 通过 + - * / // ** 等符号可以直接对DataFrame与DataFrame之间或者DataFrame以及Series之间进行运算。但秉承的原则就是对应索引运算,存在索引不同时,返回结果为索引对的并集。
  • 实际操作会发现,当存在索引不同时,返回的值自动填充NaN。
使用填充值的算数方法
方法描述
add, radd加法(+)
sub, rsub减法(-)
div, rdiv除法(/)
floordiv, rfloordiv整除(//)
mul, rmul整除(//)
pow, rpow幂次方(**)

注意:Series使用算术方法,不支持指定填充值

10.描述性统计德概述和计算

方法描述
count非NA值的个数
min,max最小值,最大值
idxmin,idxmax最小值,最大值的标签索引
sum求和
mean平均值
median中位数
var方差
std标准差
cumsum累计值
cummin,cummax累计值的最小值或最大值
cumprod值的累计积
diff计算第一个算术差值(时间序列)
pct_change百分比
corr按索引对其的值的相关性
cov协方差

11.DataFrame排序

  • df.sort_index(axis=0,ascending=True) # 索引排序

    • axis指定轴,默认为0轴
    • ascending为排序方式,默认为True表示升序
  • df.sort_values(by) # 值排序

    • by指定一列或多列作为排序键

注意
by = [col1,col2] 是先给col1排序 当col1有相同值时,col2中按排序顺序再排序

练习
关于猫的名字的统计数据,获取用次数最高的名字/

12.函数应用于映射

  • df.apply(func, axis=0) # 通过 apply 将函数运用到列 或者 行
  • df.applymap(func) # applymap将函数应用到每个数据上

三、数据清洗

1、数据清洗介绍

  • 数据清洗实际上也就是数据质量分析,检查原始数据中是否存在脏数据(不符合要求,或者不能直接进行分析的数据),并且处理脏数据。
  • 常见情况如下:
    • 缺失值
    • 异常值
    • 重复数据

2、处理缺失值

  • Pandas使用浮点值NaN(not a Number)表示缺失值,并且缺失值在数据中经常出现。那么Pandas的目的之一就是无痛的处理缺失值

1.判断数据是否为NaN

  • pd.isnull(df) 返回哪些值是缺失值的布尔值
  • pd.notnull(df) 返回值是isnull的反集
import pandas as pd
import numpy as np


df1 = pd.DataFrame([np.random.randn(3), [1., 2., np.nan], [np.nan, 4., np.nan], [1., 2., 3.]])
print(df1)


# 检测方法
print(df1.isnull().sum()) # df1.isnull().sum()默认读取数据内为Ture的个数
print(df1.notnull().sum())

注意:python内建的None值也被当作NaN值。

2.过滤缺失值

  • dropna(axis=0,how='any',inplace=False)
    • axis 指定轴 默认为0 代表行
    • how 默认为any 代表删除含有NaN的行 当为all 时代表删除所有值为NaN的行
    • inplace 修改被调用的对象 而不是一个备份
import pandas as pd
import numpy as np


df1 = pd.DataFrame([np.random.randn(3), [1., 2., np.nan], [np.nan, 4., np.nan], [1., 2., 3.]])
print(df1)


# 检测方法
print(df1.isnull().sum()) # df1.isnull().sum()默认读取数据内为Ture的个数
print(df1.notnull().sum())


# 删除缺失值
print(df1.dropna()) # 删除存在缺失值的行
print(df1.dropna(axis=1)) # 删除尊在缺失值的列
print(df1.dropna(how='all'))

3.补全缺失值

  • df.fillna(value=None,method=None,axis=None,inplace=False,limit=None)
    • value 标量或字典对象用于填充缺失值
    • method 插值方法 默认为"ffill"
    • axis 需填充的轴 默认为0
    • inplace 修改被调用的对象 而不是一个备份
    • limit 用于向前或向后填充时最大的填充范围
import pandas as pd
import numpy as np


df1 = pd.DataFrame([np.random.randn(3), [1., 2., np.nan], [np.nan, 4., np.nan], [1., 2., 3.]])
print(df1)


# 检测方法
print(df1.isnull().sum()) # df1.isnull().sum()默认读取数据内为Ture的个数
print(df1.notnull().sum())


# 删除缺失值
print(df1.dropna()) # 删除存在缺失值的行
print(df1.dropna(axis=1)) # 删除尊在缺失值的列
print(df1.dropna(how='all'))


# 填充平均值
print(df1.fillna(df1.mean()))
print(df1.fillna(method='ffill')) # 下拉填充
print(df1.fillna(method='bfill')) # 向后填充

4.异常值

  • 脏数据也包含不符合要求的数据。那么对这块数据处理不能直接使用fillna填充。使用replace更加灵活。
    • df.replace(to_replace=None,value=None)
      • to_replace 去替换的值
      • value 替换的值
import pandas as pd


# 一、数据中显性问题
## 缺失数据
## 重复数据
data = pd.read_csv('数据/guazi.csv', engine='python', encoding='utf-8')
print(data)
print(data.info()) # 查看表格信息
## 1.异常数据
print(data.drop([4, 9], inplace=True)) # 删除(4, 9)异常数据 ,仅运行一次
print(data.head())

3、处理重复数据

1.判断重复数据

  • df.duplicated(subset=None, keep='first') 返回的一个布尔值Series 默认反映的是每一行是否与之前出现过的行相同
    • subset 指定子列判断重复
    • keep 默认为first保留首个出现的 last保留最后出现的

2.删除重复数据

  • df.drop_duplicates() 返回的是DataFrame 默认删除重复行
    • subset 指定的数据任何子集是否有重复
    • keep 默认为first保留首个出现的 last保留最后出现的
import pandas as pd
import numpy as np


# 一、数据中显性问题
## 缺失数据
## 重复数据
data = pd.read_csv('数据/guazi.csv', engine='python', encoding='utf-8')
print(data)
print(data.info()) # 查看表格信息
## 1.异常数据
print(data.drop([4, 9], inplace=True)) # 删除(4, 9)异常数据 ,仅运行一次
print(data.head())

# 重新生成新的索引对象
print(data.reset_index())

# 检测
print(data.duplicated().sum())
# 删除重复数据
data.drop_duplicates(inplace=True)
print(data)

4、离散化

  • 离散化是把无限空间中有限的个体映射带有限的空间去,以此提高算法的时空效率。可以简单的理解为离散化就是将连续值进行分区间。
  • pd.cut(x,bins) 将连续数据x进行离散化
    • x 要进行离散化的数据
    • bins 分组
  • pd.value_counts(cates) 统计每个区间的数值分布
import pandas as pd
import numpy as np


ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]

#
bins = [18, 25, 35, 60, 100]

c = pd.cut(ages, bins)
# print(c)

print(pd.value_counts(c)) # 统计区间内元素的数量
print(pd.cut(ages, bins, right=False))

5、利用映射转换数据

  • 需求:如下数据。进行分班
    • 一班:胡歌,小岳岳,林更新
    • 二班:金世佳,郭麒麟
data = {
    "names":["胡歌","金世佳","林更新","郭麒麟","小岳岳"],
    "grades":np.random.randint(1,100,size=5)
}
df = pd.DataFrame(data)

使用:df[“列标签”].map(“映射到的数据”)

6、重命名标签索引

  • 需求:如下数据,将行索引名字全部转为大写
data = {
    "names":["bob","amy","cheney","jerry"],
    "grades":np.random.randint(60,100,size=4)
}

df2 = pd.DataFrame(np.random.randint(60,100,size=(4,2)),index=["bob","amy","cheney","jerry"])
df2

使用:

  • 索引映射:df.index.map()
  • 索引重命名:df.rename(index,columns)

7、向量化字符串函数

请添加图片描述
练习:读取 catNames2.csv ,找到所有的使用次数超过700并且名字的字符串的长度大于4的动物的名字

8、计算虚拟变量

分类变量转换为"虚拟"或"指标"矩阵是另一种用于统计建模或机器学习的转换操作。如果DataFrame中的一列有k个不同的值,则可以衍生一个K列的值为1和0的矩阵或DataFrame。

  • pd.get_dummies() 将分类变量转换为"虚拟"或"指标"矩阵

但是,如果说DataFrame中的一行属于多个类别,情况就会比较复杂。如下图
请添加图片描述

四、数据规整

1、索引与分层索引

1.索引

  • 查看索引:df.index
  • 指定索引:df.index = [,] 个数必须一致
  • 重置索引:df.reindex([,]) 无需个数一致
  • 指定某一列作为index:df.set_index("M",drop=False)
  • 返回index的唯一值:df.set_index("M").index.unique()
  • 将分层索引层级移动到列中:df.reset_index()

2.分层索引

  • 分层索引是Pandas一个重要的特性,允许在一个轴上拥有多个索引层级。
    请添加图片描述
import pandas as pd
import numpy as np


df = pd.DataFrame({
    'a':range(7),
    'b':range(7,0,-1),
    'c':['one','one','one','two','two','two','two'],
    'd':list("hjklmno")
})

df.set_index(["c","d"])
import pandas as pd
import numpy as np


s1 = pd.Series(np.random.randn(12),index=[['a','a','a','b','b','b','c','c','c','d','d','d'],[0,1,2,0,1,2,0,1,2,0,1,2]])
# print(s1)
# print(type(s1.index))
# print(s1.index)

# 层级索引
## 1.外层索引
# print(s1['a'])

## 2.内层索引
# print(s1['a'][0])
# print(s1[8])

# 切片
# print(s1[3:6])
#13400522220
# print(s1[3:9])

# 外层,内层为0
# print(s1[:, 0])
# print(s1.loc[:, [0, 1, 4]])


# 1.swaplevel 交换内外层
s2 = s1.swaplevel()
# print(s2)
# print(s2[0])
# print(s2.loc[[0, 1]])


print(s1.unstack()) # 转变成表,Series转变成DataFrame


# 2.sortlevel()
s3 = s1.swaplevel().sortlevel()
print(s3)

2、数据合并

  • 数据合并也就是将多个数据集拼接在一起,但是合并的方式只要分为:pandas.merge, pandas.concat, df.join

1.merge()

基于列进行关联,是做常用的一种方法。

import pandas as pd
import numpy as np


pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
         left_index=False, right_index=False)
  • left:拼接左侧的DataFrame对象;
  • right:拼接右侧的DataFrame对象;
  • on:待关联的同名列名,存在于左右两个DataFrame对象中;
  • how:连接方式,inner(默认),其他可选:outer、left、right ;
  • left_on:左侧DataFarme中用作连接键的列名;
  • right_on:右侧DataFarme中用作连接键的列;
  • left_index:将左侧的行索引用作其连接键;
  • right_index:将右侧的行索引用作其连接键;
import pandas as pd
import numpy as np


"""
创建数组1
"""
polls = {"sites":["迈皋桥", "草场门", "浦口", "奥体中心", "仙林大学城"], 
        "AQI":[55, 75, 69, 74, 58], 
        "PM25":[30, 54, 47,40 ,27], 
        "SO2":[10, 15, 13, 17, 10]}

sites = {"names":["迈皋桥", "草场门", "浦口", "奥体中心", "玄武湖"], 
        "regions":["栖霞区", "鼓楼区", "浦口区", "建邺区", "玄武区"], 
        "weather":["晴", "晴", "多云", "阴", "晴"]}
        
# 读取数据集,把字典格式转变为DataFrame格式
df_polls = pd.DataFrame(polls)
df_sites = pd.DataFrame(sites)


"""
创建数组2
"""
# 定义左侧数据集
df_left = pd.DataFrame({"sites":["迈皋桥", "草场门", "浦口", "迈皋桥", "草场门", "浦口"], 
                       "date":["2020-12-08", "2020-12-08", "2020-12-08", "2020-12-07", "2020-12-07", "2020-12-07"],  
                       "AQI":[55, 75, 69, 45, 35, 53]})
# 定义右侧数据集
df_right = pd.DataFrame({"sites":["迈皋桥", "草场门", "迈皋桥", "草场门"], 
                        "date":["2020-12-08", "2020-12-08", "2020-12-09", "2020-12-09"], 
                        "weather":["晴",  "晴", "多云", "阴"]})

"""
创建数组3
"""
sites_with_index = pd.DataFrame({"regions":["栖霞区", "鼓楼区", "浦口区", "建邺区", "玄武区"]},
                                index=["迈皋桥", "草场门", "浦口", "奥体中心", "玄武湖"])
import pandas as pd
import numpy as np


# pd.merge
# join

left = pd.DataFrame({
    'key':['K0', 'K1', 'K2', 'K3'],
    'A':['A0', 'A1', 'A2', 'A3'],
    'B':['B0', 'B1', 'B2', 'B3']
})
right = pd.DataFrame({
    'key':['K0', 'K1', 'K2', 'K3'],
    'C':['C0', 'C1', 'C2', 'C3'],
    'D':['D0', 'D1', 'D2', 'D3']
})
# print(left)
# print(right)

p1 = pd.merge(left, right, on='key') # on='key'指定公用键
# print(p1)


df3 = pd.DataFrame({
    'name':['mark', 'Bob', 'Sam', 'Jake'],
    'group':['IT部', 'HR部', '运营部', '设计部']
})
df4 = pd.DataFrame({
    'name':['Sam', 'Bob', 'mark', 'Jake'],
    'date':[2004, 2008, 2012, 2014]
})
# print(df3)
# print(df4)
# print(pd.merge(df3, df4))





left = pd.DataFrame({
    'key1':['K0', 'K1', 'K1', 'K2'],
    'key2':['K0', 'K1', 'K0', 'K1'],
    'A':['A0', 'A1', 'A2', 'A3'],
    'B':['B0', 'B1', 'B2', 'B3']
})
right = pd.DataFrame({
    'key1':['K0', 'K1', 'K1', 'K2'],
    'key2':['K0', 'K0', 'K0', 'K0'],
    'C':['C0', 'C1', 'C2', 'C3'],
    'D':['D0', 'D1', 'D2', 'D3']
})
print(pd.merge(left, right, how='inner')) # 默认连接方式,内连接,数据交集
print(pd.merge(left, right, how='outer')) # 全连接,外连接,数据并集
print(pd.merge(left, right, how='lift')) # 左连接
print(pd.merge(left, right, how='right')) # 右连接

2.join()

join方法是基于index连接dataframe。join连接方法有内连接,外连接,左连接和右连接,与merge一致。

import pandas as pd
import numpy as np


"""
创建数组4
"""
polls_with_index = pd.DataFrame({"AQI":[55, 75, 69, 74, 58], 
                                 "PM25":[30, 54, 47,40 ,27], 
                                 "SO2":[10, 15, 13, 17, 10]}, 
                                index=["迈皋桥", "草场门", "浦口", "奥体中心", "仙林大学城"])

3.concat()

另外一种常用的数据整合方法是concat,即我希望按照某种方式把两个规整的数据集进行拼接。

import pandas as pd
import numpy as np


pd.concat(objs, axis=0, join='outer', keys=None)
  • objs:带拼接的数据集,通常以列表的形式传入;
  • join:可选inner、outer,含义同merge函数;
  • keys:定义新的分组索引,用来区分传入的数据集;
import pandas as pd
import numpy as np


"""
创建数组5
"""
new_polls = {"sites":["迈皋桥", "草场门", "浦口", "奥体中心", "仙林大学城"], 
        "AQI":[65, 85, 79, 78, 78], 
        "PM25":[50, 74, 67,60 ,47], 
        "O2":[20, 35, 23, 37, 15]}
        
df_polls_new = pd.DataFrame(new_polls)
import pandas as pd
import numpy as np


# numpy数组的合并
x = np.array([[1, 2], [3, 4]])
y = np.array([[5, 6], [7, 8]])
# print(x)
# print(y)
# x1 = np.concatenate([x, y], axis=1)
# print(x1)

df1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=list('abc'), columns=['one', 'two'])
df2 = pd.DataFrame(np.arange(4).reshape(2, 2)+5, index=list('ac'), columns=['one', 'two'])
print(df1)
print(df2)

## 合并数据
# 1.  append
d1 = df1.append(df2)
# print(d1)

# 2.  concat
d2 = pd.concat([df1, df2], axis=1, sort=True)
print(d2)

3、数据分组与聚合

数据包含在Series、DataFrame数据结构中,可以根据一个或多个键分离到各个组中。分组操作之后,一个函数就可以应用到各个组中,产生新的值。
请添加图片描述

  • df.groupby('key') key为指定分组的列
import pandas as pd
import numpy as np

df1 = pd.DataFrame(
    {
        "names":["菲菲","小可爱","mia","牛哥","老王","mia","狼人","药水哥","药水哥"],
        "classes":["一班","二班","三班"]*3,
        "grades":np.random.randint(60,100,size=9)
    }
)
df1

df1.groupby(by="classes")["grades"].mean()

聚合函数如下:
请添加图片描述

import pandas as pd
import numpy as np

df1 = pd.DataFrame({
    'fruit':['apple', 'banana', 'orange', 'apple', 'banana'],
    'color':['red', 'yellow', 'yellow', 'cyan', 'cyan'],
    'price':[8.5, 6.8, 5.6, 7.8, 6.4]
})
# print(df1)
# 求苹果的平均价格
# df2 = df1[df1['fruit'] == 'apple']
# print(df2)
# n = df2['price'].sum()/len(df2)
# print(n)
#
# df2 = df1.groupby(by='fruit')
# for name,group in df2:
#     print(name)
#     print('*'*30)
#     print(group)
# 求苹果的平均价格
# df2 = dict(list(df1.groupby(by='fruit')))['apple']
# print(df2)
df2 = df1.groupby(by='fruit')['price'].mean()
# print(df2)
# 语法糖
df3 = df1.groupby(by='fruit')[['price']].mean()
# print(df3)

df4 = df1.groupby(by=['fruit', 'color'])['price'].mean()
# print(df4)
df5 = df1.groupby(by=['fruit', 'color'])['price'].mean().unstack()
# print(df5)

1.自定义聚合函数

实现步骤:

  • 自定义函数
  • 分组后通过agg或者aggregate进行聚合
import pandas as pd
import numpy as np


def classes_ptp(x):
    return x.max()-x.min()

df1.groupby(by="classes")["grades"].agg(classes_ptp)
df1.groupby(by="classes")["grades"].aggregate(classes_ptp)

2.分组块上应用函数

实现步骤:

  • 定义函数
  • 通过apply方法将函数应用到分组后的数组
import pandas as pd
import numpy as np


def sort_df(df):
    return df.sort_values(by="grades")

df1.groupby(by="classes").apply(sort_df)

除了以上分组形势,还可以通过字典、series、函数进行分组。

import pandas as pd
import numpy as np


df2 = pd.DataFrame(
    np.random.randint(60,100,size=(5,3)),
    index=["菲菲","小可爱","mia","牛哥","老王"],
    columns=["语文","数学","英语"]
)
df2

五、时间序列

1、时间序列前言

时间序列数据在很多领域都是重要的结构化数据形式,比如:金融,神经科学,生态学,物理学。在多个时间点观测的数据形成了时间序列。时间序列可以是固定频率的,也可以是不规则的。

1.常见使用

@1时间戳
import pandas as pd
import numpy as np
import time


time.time()
@2结构化时间
import pandas as pd
import numpy as np
import time


t = time.localtime(time.time()) # 转化为本地时区
print(t)
g = time.gmtime(time.time()) # 转化为0时区
print(g)
print(t.tm_mday)
@3格式化时间字符串
import pandas as pd
import numpy as np
import time


PM = time.strftime('%Y-%m-%d %H:%M:%S',t)
print(PM)
q = time.strptime('2021-08-14 15:13:25', '%Y-%m-%d %H:%M:%S')
print(q)
@4生成时间字符串
import pandas as pd
import numpy as np
import time


w = time.ctime(time.time())
print(w)
@5偏移量取整
import pandas as pd
import numpy as np
import time


m = time.mktime(t)
print(m)
@6固定的时间区间
import pandas as pd
import numpy as np
from datetime import datetime


# 日期模块和实际数据类型
now = datetime.now() # 取现在时间
print(now)
print(now.year, now.month, now.day)
@7时间间隔
import pandas as pd
import numpy as np
from datetime import datetime


d = datetime(2021, 12, 12, 20, 0, 0) - datetime(2021, 12, 11, 1, 0, 0)
print(d)
print(type(d))

@8datetime和字符串相互转换
import pandas as pd
import numpy as np
from datetime import datetime


stamp = datetime(2021, 8, 12)
# 强制转换
print(str(stamp))
# 格式化(可自定义符号)
print(stamp.strftime('%Y-%m-%d %H:%M:%S'))

d = ['12/12/2021 20:00:00', '1/1/2021 12:00:00']
p = pd.to_datetime(d)
print(p)

2、时间序列基础

1.时间序列介绍

Pandas中的基础时间序列种类是由时间戳索引的Series,在Pandas外部通常表示为Python字符串或datetime对象。
注意

  • datetime对象可作为索引,时间序列DatetimeIndex
  • <M8[ns]类型为纳秒级时间戳
  • 时间序列里面每个元素为Timestamp对象

2.生成时间序列函数

  • pd.date_range(start=None,end=None,periods=None,freq=None,tz=None,normalize=False)
    • start 起始时间
    • end 结束时间
    • periods 固定时期
    • freq 日期偏移量(频率)
    • normalize 标准化为0的时间戳
import pandas as pd
import numpy as np


d1 = pd.date_range(start="20200101",end="20200201") 
d1

d2 = pd.date_range(start="20200101",end="20200201",periods=5) 
d2

d3 = pd.date_range(start="20200101",periods=5,freq="10D")
d3

d4 = pd.date_range(start="2020-01-01 12:59:59",periods=5,freq="10D",normalize=True)
d4

关于频率设置如下:
请添加图片描述
具体可参考https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#timeseries-offset-aliases

3.时间序列的索引及索引数据

import pandas as pd
import numpy as np


ts=pd.Series(np.random.randint(1,100,size=800),index=pd.date_range("20180101",periods=800))
ts

# 选择2020的数据 
ts['2020']        

# 选择2020的一月份数据
ts['2020 01']     

# 取2020年5月01至5月10的数据
ts['2020 05 01':'2020 05 10']

4.含有重复索引的时间序列

  • df.indexis_unique 检查索引是否唯一

5.移位日期

"移位"指的是将日期按时间向前移动或向后移动。Series和DataFrame都有一个shift方法用于进行简单的前向或后向移位 而不改变索引

import pandas as pd
import numpy as np


ts=pd.Series(np.random.randint(1,100,size=800),index=pd.date_range("20180101",periods=800))


ts.shift(2)   # 向前移动

ts.shift(-2)  # 向后移动

3、重采样

1.重采样介绍

  • 重采样:指的是将时间序列从一个频率转化为另一个频率进行处理的过程,将高频率数据转化为低频率数据为降采样,低频率转化为高频率为升采样
import pandas as pd
import numpy as np


ts = pd.DataFrame(np.random.randint(100,200,size=100),index=pd.date_range(start="20200101",periods=100))
ts

ts.resample("M").mean()

以上为时间序列的基本内容。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(1000,4000,size=(4,4)),index=[20200101,20200102,20200103,20200104],columns=["北京","上海","广州","深圳"])
df
  • 该行索引类型并不是时间序列类型,所以我们想要使用时间序列的特性,就需要将其转为时间序列。通过 pd.to_datetime(),其中的format参数可以调试时间序列的格式,常用如下:
    请添加图片描述

六、数据读取存储

请添加图片描述
请添加图片描述

1、CSV文件

  • 读取csv文件read_csv(file_path or buf,usecols,encoding):file_path:文件路径,usecols:指定读取的列名,encoding:编码
import pandas as pd
import numpy as np


data = pd.read_csv('d:/test_data/food_rank.csv',encoding='utf8')
data.head()
    name    num
0    酥油茶    219.0
1    青稞酒    95.0
2    酸奶    62.0
3    糌粑    16.0
4    琵琶肉    2.0

#指定读取的列名
data = pd.read_csv('d:/test_data/food_rank.csv',usecols=['name'])
data.head()
    name
0    酥油茶
1    青稞酒
2    酸奶
3    糌粑
4    琵琶肉

#如果文件路径有中文,则需要知道参数engine='python'
data = pd.read_csv('d:/数据/food_rank.csv',engine='python',encoding='utf8')
data.head()
    name    num
0    酥油茶    219.0
1    青稞酒    95.0
2    酸奶    62.0
3    糌粑    16.0
4    琵琶肉    2.0
#建议文件路径和文件名,不要出现中文
  • 写入csv文件DataFrame:to_csv(file_path or buf,sep,columns,header,index,na_rep,mode):file_path:保存文件路径,默认None,sep:分隔符,默认’,’ ,columns:是否保留某列数据,默认None,header:是否保留列名,默认True,index:是否保留行索引,默认True,na_rep:指定字符串来代替空值,默认是空字符,mode:默认’w’,追加’a’
**Series**:`Series.to_csv`\(_path=None_,_index=True_,_sep='_,_'_,_na\_rep=''_,_header=False_,_mode='w'_,_encoding=None_\)

2、数据库交互

  • pandas
  • sqlalchemy
  • pymysql
#  导入必要模块
import pandas as pd
from sqlalchemy import create_engine

#初始化数据库连接
#用户名root 密码   端口 3306  数据库 db2
engine = create_engine('mysql+pymysql://root:@localhost:3306/db2')
#查询语句
sql = '''
    select * from class;
'''
#两个参数   sql语句  数据库连接
df = pd.read_sql(sql,engine)
df

请添加图片描述

#新建
df = pd.DataFrame({'id':[1,2,3,4],'num':[34,56,78,90]})
df = pd.read_csv('ex1.csv')
# #写入到数据库
df.to_sql('df2',engine,index=False)
print("ok")

进入数据库查看 :
请添加图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值