一、为什么要学习pandas

numpy已经可以帮助我们处理数据,能够结合matplotlib进行数据分析,那学习pandas的目的又是什么呢?numpy只能够帮我们处理数值型的数据,但这还不够。很多时候,我们处理的数据中除了数值型的数据,还有字符串、时间序列等等,这个时候就需要使用pandas来处理这些特殊类型的数据。当然了pandas是基于numpy的,也可以处理数值型的数据

二、什么是pandas

引用官方文档的一句话:

pandas is an open source, BSD-licensed library providing high-performence, easy-to-use data structures and data analysis tools for the Python programming language.

pandas是BSD许可的开源库,为Python编程语言提供了高性能,易于使用的数据结构和数据分析工具

三、pandas常用数据类型

  1. Series:一维,带标签的数组,标签也就是索引
  2. DataFrame :二维,Series容器,一列是一个Series

四、Series一维容器

1、创建Series

import pandas as pd
# 创建时传入可迭代对象即可
s1 = pd.Series(range(10, 20)) # 不指定索引,索引默认从0开始递增
s2 = pd.Series(range(6), index=list("ABCDEF")) # 指定索引

也可通过字典创建Series,键为索引,对应的值为数据

# 字典创建
temp_dict = {'name': 'wang', 'age': 20, 'tel':10010, 'like':'sleep'}
s3= pd.Series(temp_dict) # 键为索引,对应的值为数据

2、索引和切片

通过索引取值

name = s3["name"] 
age = s3["age"]
tel = s3["tel"]

通过位置取连续的值

name, age = s3[0:2]
like = s3[3]
age, tel, like = s3[1:]

取不连续的值(方括号嵌套方括号的形式)

s3[[0,2]]  # 获取0行和2行
s3[["name", "like"]]) # 获取name行和like行

布尔索引

s = pd.Series(range(10, 20))
s < 13 # s中数值小于13的返回True,大于等于13的返回False
s[s < 13] # bool索引,返回值小于13的行组成的Series
s.where(s > 13, 100) # s中小于等于13的替换为100
s.where(s > 13) # 返回Series对象,其中值大于13保持原值,小于等于13的变成NaN

index和values的相关操作

temp_dict = {'name': 'wang', 'age': 20, 'tel':10010, 'like':'sleep'}
s3= pd.Series(temp_dict) # 键为索引,对应的值为数据
name, age, tel, like = s3.index # 返回索引,pandas.core.indexes.base.Index类型的对象
s3.values # 返回values,numpy.ndarray类型的对象
len(s3.index) # 获取可迭代对象长度
len(s3.values)
list(s3.index) # 可迭代对象转换为列表
list(s3.values)

五、DataFrame (二维容器)

DataFrame是二维的,有index(横向索引)和column(纵向索引),对应axis=0和axis=1,不指定索引也是默认从0递增

1、创建DataFrame
import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.arange(12).reshape(3,4), index=list("abc"), columns=list("wxyz"))
print(df1)

df1 如下:

pandas详细笔记_数据


通过字典创建DataFrame

= {'name': ['wang', "zhang"], 'age': [20, 34], 'tel':[10010,10086]}
df2 = pd.DataFrame(temp_dict) # 键为索引,对应的值为数据

pandas详细笔记_迭代_02


通过列表创建DataFrame

= [{'name': 'wang', 'age': 20, 'tel':10086},{'name': 'huang', 'tel':10086},{'name': 'wang','like':'sleep', 'tel':10086}]
df2 = pd.DataFrame(temp_list)

df2 如下:

pandas详细笔记_迭代_03


可以看到,若有的数据没有对应的列则用NaN(Not a Number)表示

2、DataFrame的基础属性
  • df.shape # 返回行数和列数
  • df.dtypes # 返回列数据类型
  • df.index # 返回行索引
  • df.column # 返回列索引
  • df.values # 返回数据值,不包含索引
  • df.info() # 返回相关信息,行数、列数、列非空个数、列类型、内存占用等
  • df.describe() # 快读统计综合结果,计数、均值、标准差、最大最小值等
  • df.head(3) # 返回数据的前3行,默认5行
  • df.tail(3) # 返回数据的后3行,默认5行
["age"].argmax()  # 指定列最大值的索引
df2["age"].argmin() # 指定列最小值的索引
df2["age"].max() # 指定列最大值
df2["age"].min() # 指定列最小值
df2["age"].median() # 指定列中位数
df2["age"].mean() # 指定列平均值
df2["hobby"] # 获取hobby列
3、索引和切片

df1 如下:

pandas详细笔记_迭代_04


loc通过 标签 获取数据

.loc["a"]  # 取a行
df1.loc["a",:] # 取a行,同上
df1.loc["W"] # 报错,只能取行,不能取列
df1.loc[:,"W"] # 取W列
df1.loc["a","W"] # 取a行和W列相交的元素
df1.loc[["a", "b"]] # 取a列和b行
df1.loc[["a","b"], :] # 取a行和b行,同上
# 取a行、c行和W列、Y列相交的4个元素,在numpy中只能取出两个元素
df1.loc[["a", "c"], ["W", "Y"]]
df1.loc["a":"c", ["W"]] # 使用loc进行切片索引时,最后一个c是可以选中的,从a到c,和w列相交的3个数据

iloc通过 位置 获取数据

.iloc[1,:]  # 取第1行数据
df1.iloc[:,1:] # 取第1列以及往后的所有数据
# 取1行、2行和2列、2列相交的4个元素,若在numpy中取得是df1[1][2]和df1[2][3]
df1.iloc[[1,2],[2,3]]
df1.iloc[:,[0,2]] # 取第0列和第2列
# 把0行和1行赋值成NaN,在numpy中直接赋值会报错,应转换为float
df1.iloc[:2] = np.nan

注意区分:

[0]  # 获取第0列
df1.loc[0] # 获取第0行
df1.iloc[0] # 获取第0行
4、关于缺失值的处理
  • isnull():值为NaN的数据则返回True,否则返回False
  • notnull():值为NaN的数据则返回False,否则返回True
  • dropna():删除DataFrame中含有NaN行
  • axis参数:可选0、1,表示删除谋和轴的NaN
  • how参数:可选all、any,all表示删除全为NaN的行,any表示删除含有
    NaN的行
  • fillna():用其他值填充NaN

df2 如下:

pandas详细笔记_字符串_05

.isnull(df2)  # NaN返回True
pd.notnull(df2) # NaN返回False
df2[pd.notnull(df2["hobby"])] # 选取hobby列不为NaN的所在行
df2.dropna(axis=0, how="all") # 删除0轴全为NaN的行
df2.dropna(axis=0, how="any") # 删除0轴有NaN的行
df2.dropna(axis=0, how="any", inplace=True) # 原地修改
# 用df2每一列的均值(不算NaN)填充对应列的NaN,pandas计算比numpy计算智能
df2.fillna(df2.mean()) # 用数字列的平均值填充改列的NaN
df2["age"] = df2["age"].fillna(df2["age"].mean()) # 用age列的平均值填充age列的NaN

六、pandas常用方法

  • contains返回表示各字符串是否含有指定模式的布尔型数组
  • count模式的出现次数
  • endswith, startswith相当于对各个元索执行x.endswith(pattern)或 x.startswith(pattern)
  • findall计算各字符串的模式列表
  • get获取各元素的第i个字符
  • join根据指定的分隔符将Series中各元索的字符串连接起来
  • len计算各字符串的长度
  • lower, upper转换大小写,相当于对各个元素执行x.lower()或x.upper()
  • match根裾指定的正则表达式对各个元素执行re.match
  • pad在字符串的左边、右边或左右两边添加空白符
  • center相当于pad(side=_both)
  • repeat重复值,例如,s.str.repeat(3)相当于对各个字符串执行x*3
  • replace用指定字符串替换找到的裉式
  • slice对Series中的各个字符串进行子串截取
  • split根据分隔符或正则表达式对字符串进行拆分
  • strip, rstrip, Istrip去除空白符,包括换行符.相当于对各个元索执行x.strip()、 x.rstrip(), x.lstrip()

七、案例

分析狗名字的使用次数
数据来源:​​​https://www.kaggle.com/new-york-city/nyc-dog-names/data​

首先读取CSV文件,并打印数据有关信息,以便后续操作

= './dogNames2.csv'
df = pd.read_csv(file_path)
print(df.head())
print("-"*100)
print(df.info())

通过打印的信息,我们得到相关信息如下

pandas详细笔记_数据_06


查看被用得最多的前10个狗名字以及使用次数

这时我们得先按照名字被使用的次数降序排列,然后取前10行

= df.sort_values(by="Count_AnimalName", ascending=False)
print(df.iloc[:10])

得到名字以及使用次数:

pandas详细笔记_迭代_07


获取使用次数在区间[800,1000]内的名字

print(df[(df["Count_AnimalName"]>=800) & (df["Count_AnimalName"]<=1000)]["Row_Labels"])

获取名字长度大于10的数据

print(df[df["Row_Labels"].str.len()>10])