什么是Pandas? Pandas的名称来自于面板数据(panel data)和Python数据分析(data analysis). Pandas是一个强大的分析结构化数据的工具集,基于NumPy构建,提供了 高级数据结构 和 数据操作工具,它
什么是Pandas?
- Pandas的名称来自于面板数据(panel data)和Python数据分析(data analysis).
- Pandas是一个强大的分析结构化数据的工具集,基于NumPy构建,提供了 高级数据结构 和 数据操作工具,它是使Python成为强大而高效的数据分析环境的重要因素之一.
- 一个强大的分析和操作大型结构化数据集所需的工具集
- 基础是NumPy,提供了高性能矩阵的运算
- 提供了大量能够快速便捷地处理数据的函数和方法
- 应用于数据挖掘,数据分析
- 提供数据清洗功能
pandas官网: http://pandas.pydata.org
pandas的常用数据类型:
- Series 一维,带标签数组
- DataFrame 二维,Series容器
Series:
Series是一种类似于一维数组的 对象,由一组数据(各种NumPy数据类型)以及一组与之对应的索引(数据标签)组成.
类似一维数组的对象
由数据和索引组成
索引(index)在左,数据(values)在右
索引是自动创建的
Series创建:
In [1]: import pandas as pdIn [2]: import string
In [3]: import numpy as np
In [4]: t = pd.Series(np.arange(10),index=list(string.ascii_uppercase[:10]))
——>指定索引创建
In [5]: t
Out[5]:
A 0
B 1
C 2
D 3
E 4
F 5
G 6
H 7
I 8
J 9
dtype: int64
In [6]: type(t)
Out[6]: pandas.core.series.Series
---------------------------------
In [7]: a = {string.ascii_uppercase[i]: i for i in range(10)}
——>通过字典推导式创建一个字典
In [8]: a
Out[8]:
{'A': 0,
'B': 1,
'C': 2,
'D': 3,
'E': 4,
'F': 5,
'G': 6,
'H': 7,
'I': 8,
'J': 9}
In [9]: pd.Series(a) ——>通过字典创建一个Series,索引对应字典中的键
Out[9]:
A 0
B 1
C 2
D 3
E 4
F 5
G 6
H 7
I 8
J 9
dtype: int64
In [10]: pd.Series(a,index=list(string.ascii_uppercase[5:15]))
Out[10]:
F 5.0 重新给字典指定其他的索引之后,如果能够对应上,就取其
G 6.0 值,如果不能,就为Nan
H 7.0
I 8.0
J 9.0
K NaN
L NaN
M NaN
N NaN
O NaN
dtype: float64
为什么类型为float呢?
numpy中nan为float,pandas会 自动根据数据类更改series的dtype类型
如果要修改dtype类型,修改方法和numpy的方法一样
如: pd.Series(range(10)).astype(float)
Series切片和索引:
In [15]: tOut[15]:
A 0
B 1
C 2
D 3
E 4
F 5
G 6
H 7
I 8
J 9
dtype: int64
In [16]: t[2::2] # 切片操作
Out[16]:
C 2
E 4
G 6
I 8
dtype: int64
In [17]: t[2] # 根据索引取值
Out[17]: 2
In [18]: t[[2,3,6]] # 取不连续的值
Out[18]:
C 2
D 3
G 6
dtype: int64
In [19]: t[t>4] # 布尔索引
Out[19]:
F 5
G 6
H 7
I 8
J 9
dtype: int64
In [20]:
In [20]: t["F"] # 根据键取值
Out[20]: 5
In [22]: t[["A","F"]] # 取不连续的值
Out[22]:
A 0
F 5
dtype: int64
切片:直接传入start end或者步长即可
索引: 一个的时候直接传入序号或者index,多个的时候传入序号或者index的列表
Series的索引和值:
In [25]: t.indexOut[25]: Index(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], dtype='object')
In [26]: t.values
Out[26]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [27]: type(t.values)
Out[27]: numpy.ndarray
Series对象本质上由两个数组构成,一个数组构成对象的键(index,索引),
一个数组构成对象的值(values), 键——>值
ndarray的很多方法都可以运用于series类型,比如argmax, clip
series具有where方法,但是结果和ndarray不同
如:
In [30]: t.where(t>2)
Out[30]:
A NaN
B NaN
C NaN
D 3.0
E 4.0
F 5.0
G 6.0
H 7.0
I 8.0
J 9.0
dtype: float64
pandas读取外部数据:
我们的这组数据存在csv中,我们直接使用pd.read_csv即可和我们想象的有些差别,我们以为他会是一个Series类型,但是他是一个DataFrame,
那么接下来我们就来了解这种数据类型
对于数据库比如mysql或者mongodb中数据我们如何使用呢?
读取mysql: pd.read_sql(sql_sentence,connection)
读取mongodb:
client = MongoClient()
collection = client["douban"]["t1"]
data = list(collection.find())
t1 = data[0]
t1 = pd.Series(t1)
DataFrame:
In [31]: t = pd.DataFrame(np.arange(12).reshape(3,4))In [32]: t
Out[32]:
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
DataFrame对象既有行索引,又有列索引
行索引,表明不同行,横向索引(竖着的索引),叫index,0轴,axis=0
列索引,表名不同列,纵向索引(横着的索引),叫columns,1轴,axis=1
In [35]: t = pd.DataFrame(np.arange(12).reshape(3,4),index=list("ABC"),columns=list("WXYZ"))
In [36]: t
Out[36]:
W X Y Z
A 0 1 2 3
B 4 5 6 7
C 8 9 10 11
向DataFrame中传入字典:
In [37]: data = {"name":["xiaowang","xiaoli"],"age":[13,14],"id":[1001,1002]}
In [38]: data
Out[38]: {'name': ['xiaowang', 'xiaoli'], 'age': [13, 14], 'id': [1001, 1002]}
In [39]: pd.DataFrame(data)
Out[39]:
name age id
0 xiaowang 13 1001
1 xiaoli 14 1002
这就意味着我们可以直接将mongodb中的数据传入到DataFrame中
列表里面套字典:
In [46]: data = [{"age":18,"id":1001,"name":"aa"},{"name":"bb","id":1002},
... {"name":"cc","age":16}]
In [47]: data
Out[47]:
[{'age': 18, 'id': 1001, 'name': 'aa'},
{'name': 'bb', 'id': 1002},
{'name': 'cc', 'age': 16}]
In [48]: pd.DataFrame(data)
Out[48]:
age id name
0 18.0 1001.0 aa
1 NaN 1002.0 bb
2 16.0 NaN cc
DataFrame的基础属性:
df.shape # 行数列数df.dtypes # 列数据类型
df.ndim # 数据维度
df.index # 行索引
df.columns # 列索引
df.values # 对象值,二维ndarray数组
DataFrame整体情况查询:
df.head(3) # 显示头部几行,默认5行df.tail(3) # 显示末尾几行,默认5行
df.info() # 相关信息概览:行数,列数,列索引,列非空值个数,列类型,列类型,内存占用
df.describe() # 快速综合统计结果:计数,均值,标准差,最大值,四分位数,最小值
常用的统计描述方法:
方法 说明count 非NA值的数量
describe 针对Series或各DataFrame列计算汇总统计
min、max 计算最小值和最大值
argmin、argmax 计算能够获取到最小值和最大值的索引位置(整数)
idxmin、idxmax 计算能够获取到最小值和最大值的索引值
quantile 计算样本的分位数(0到1)
sum 值的总和
mean 值的平均数
median 值的算术中位数(50%分位数)
mad 根据平均值计算平均绝对离差
var 样本值的方差
std 样本值的标准差
skew 样本值的偏度(三阶矩)
kurt 样本值的峰度(四阶矩)
cumsum 样本值的累计和
cummin、cummax 样本值的累计最大值和累计最小值
cumprod 样本值的累计积
diff 计算一阶差分(对时间序列很有用)
pct_change 计算百分数变化
排序:
# by指定排序的字段,ascending默认为True,升序.df.sort_values(by="Count_AnimalName",ascending=False)
取行或者列:
df_sorted = df.sort_values(by="Count_AnimalName")选择行 df_sorted[:100]
我们具体要选择某一列该怎么选择呢? df["Count_AnimalName "]
我们要同时选择行和列改怎么办? df[:100][" Count_AnimalName "]
pandas之loc:
df.loc 通过标签索引行数据.In [50]: t
Out[50]:
W X Y Z
A 0 1 2 3
B 4 5 6 7
C 8 9 10 11
In [51]: t.loc["A","W"] # 取某个指定元素
Out[51]: 0
In [52]: t.loc["A",["W","Z"]] # 取一行和不连续多列
Out[52]:
W 0
Z 3
Name: A, dtype: int64
In [53]: type(t.loc[["A"],["W","Z"]]) # 类型为DataFrame
Out[53]: pandas.core.frame.DataFrame
In [54]: t.loc[["A","C"],["W","Z"]] # 取不连续的多行和多列
Out[54]:
W Z
A 0 3
C 8 11
In [55]: t.loc["A":,["W","Z"]] # 取多行和多列("A"及以后的行)
Out[55]:
W Z
A 0 3
B 4 7
C 8 11
In [56]: t.loc["A":"C",["W","Z"]] # 取多行和多列,("A"到"C"行)
Out[56]:
W Z
A 0 3
B 4 7
C 8 11
冒号在loc里面是闭合的,即会选择到冒号后面的数据
pandas之iloc:
df.iloc 通过位置获取行数据In [57]: t
Out[57]:
W X Y Z
A 0 1 2 3
B 4 5 6 7
C 8 9 10 11
In [58]: t.iloc[1:3,[2,3]]
Out[58]:
Y Z
B 6 7
C 10 11
In [59]: t.iloc[1:3,1:3]
Out[59]:
X Y
B 5 6
C 9 10
In [60]: t.loc["A","Y"]=100 # 更改数据
In [61]: t
Out[61]:
W X Y Z
A 0 1 100 3
B 4 5 6 7
C 8 9 10 11
In [62]: t.iloc[1:2,0:2] = np.nan # 此处panads会自动转换类型
In [63]: t
Out[63]:
W X Y Z
A 0.0 1.0 100 3
B NaN NaN 6 7
C 8.0 9.0 10 11
pandas之布尔索引:
在给定的数据集中:假如我们想找到所有的使用次数超过800的狗的名字,应该怎么选择?数据来源:https://www.kaggle.com/new-york-city/nyc-dog-names/data
In [67]: df = pd.read_csv("./笔记/python/dogNames2.csv")
In [68]: df[800<df["Count_AnimalName"]]
Out[68]:
Row_Labels Count_AnimalName
1156 BELLA 1195
2660 CHARLIE 856
3251 COCO 852
9140 MAX 1153
12368 ROCKY 823
回到之前狗的名字的问题上,假如我们想找到所有的使用次数超过700并且名字的字符串的长度大于4的狗的名字,
应该怎么选择?
In [71]: df[(df["Row_Labels"].str.len()>4) & (df["Count_AnimalName"]>700)]
Out[71]:
Row_Labels Count_AnimalName
1156 BELLA 1195
2660 CHARLIE 856
8552 LUCKY 723
12368 ROCKY 823
------------------------------------
&表示且,|表示或
注意: 不同的条件直接需要用括号括起来
pandas之str字符串方法:
方法 说明cat 实现元素级的字符串连接操作,可指定分隔符
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.lstrip 去除空白符,包括换行符.相当于对各个元素执行x.strip(),x.rstrip(),x.lstrip()
例: df["Row_Labels"].str.len()
缺失数据的处理:
我们的数据缺失通常有两种情况:一种就是空,None等,在pandas是NaN(和np.nan一样)
另一种是我们让其为0
对于NaN的数据,在numpy中我们是如何处理的?
在pandas中我们处理起来非常容易
判断数据是否为NaN:pd.isnull(df),pd.notnull(df)
处理方式1:删除NaN所在的行列dropna (axis=0, how='any', inplace=False)
处理方式2:填充数据,t.fillna(t.mean()),t.fiallna(t.median()),t.fillna(0)
处理为0的数据:t[t==0]=np.nan
当然并不是每次为0的数据都需要处理
计算平均值等情况,nan是不参与计算的,但是0会
-------------------------------
In [76]: t2
Out[76]:
age id name
0 18.0 1001.0 aa
1 NaN 1002.0 bb
2 16.0 NaN cc
In [77]: pd.isnull(t2) # NaN的位置显示为True
Out[77]:
age id name
0 False False False
1 True False False
2 False True False
In [78]: pd.notnull(t2) # 非NaN的位置显示为True
Out[78]:
age id name
0 True True True
1 False True True
2 True False True
In [81]: t2[pd.notnull(t2["age"])] # 显示年龄不为NaN的行
Out[81]:
age id name
0 18.0 1001.0 aa
2 16.0 NaN cc
In [82]: t2.dropna(axis=0) # 去除NaN所在的行
Out[82]:
age id name
0 18.0 1001.0 aa
In [83]: t2.dropna(axis=0,how="all") # "all"代表这一行全部为NaN的时候才去除这一行
Out[83]:
age id name
0 18.0 1001.0 aa
1 NaN 1002.0 bb
2 16.0 NaN cc
In [84]: t2.dropna(axis=0,how="any") # how参数默认的值为"any"
Out[84]:
age id name
0 18.0 1001.0 aa
In [87]: t2.dropna(axis=0,how="any",inplace=True) # inplace参数代表在原数据的基础上去除,默认返回去除后的数据
In [88]: t2
Out[88]:
age id name
0 18.0 1001.0 aa
In [91]: t2
Out[91]:
age id name
0 18.0 1001.0 aa
1 NaN 1002.0 bb
2 16.0 NaN cc
In [92]: t2.fillna(0) # 将NaN的地方填充为0
Out[92]:
age id name
0 18.0 1001.0 aa
1 0.0 1002.0 bb
2 16.0 0.0 cc
In [93]: t2.fillna(t2.mean()) # 将NaN的地方填充所在列的均值
Out[93]:
age id name
0 18.0 1001.0 aa
1 17.0 1002.0 bb
2 16.0 1001.5 cc
In [94]: t2["age"] = t2.fillna(t2["age"].mean()) # 指定填充”age“列的NaN
In [95]: t2
Out[95]:
age id name
0 18 1001.0 aa
1 17 1002.0 bb
2 16 NaN cc
-------------------------------
pandas常用统计方法:
- 假设现在我们有一组从2006年到2016年1000部最流行的电影数据,我们想知道这些电影数据中评分的平均分,导演的人数等信息,我们应该怎么获取?
- 数据来源:https://www.kaggle.com/damianpanek/sunday-eda/data
数据样式:
Rank, Title, Genre, Description, Director, Actors, Year, Runtime (Minutes),Rating,Votes,Revenue (Millions),Metascore1,Guardians of the Galaxy,"Action,Adventure,Sci-Fi",A group of intergalactic criminals are forced to work together to stop a fanatical warrior from taking control of the universe.,James Gunn,"Chris Pratt, Vin Diesel, Bradley Cooper, Zoe Saldana",2016, 108, 7.2, 60545, 270.32, 59
代码:
import pandas as pdpath = "./IMDB-Movie-Data.csv"
# 读取数据
df = pd.read_csv(path)
# 数据的基本信息
print(df.info())
# 取第一行数据类观察数据
print(df.head(1))
# 求均值
print(df["Rating"].mean())
# 提取导游数据转换成列表,在转换成集合去掉重复的,然后求长度即可
print(len(set(df["Director"].tolist())))
print(len(df["Director"].unique()))
# 提取演员信息,利用列表推导式的双重for将双重列表装换成单层
temp_list = df["Actors"].str.split(", ").tolist()
temp_list = [j for i in temp_list for j in i]
print(len(set(temp_list)))
# 电影时长的最大值和最小值以及中位数
print(df["Runtime (Minutes)"].max())
print(df["Runtime (Minutes)"].argmax())
print(df["Runtime (Minutes)"].min())
print(df["Runtime (Minutes)"].argmin())
print(df["Runtime (Minutes)"].median())
- 对于这一组电影数据,如果我们想rating,runtime的分布情况,应该如何呈现数据?
runtime代码:
import pandas as pdfrom matplotlib import pyplot as plt
path = "./IMDB-Movie-Data.csv"
# 准备数据
df = pd.read_csv(path)
# 提取
runtime_data = df["Runtime (Minutes)"].values
max_runtime = runtime_data.max()
min_runtime = runtime_data.min()
# 组数
d = 5
bin_nums = (max_runtime - min_runtime)//d
# 设置图片大小
plt.figure(figsize=(20,8),dpi=80)
# 选择直方图
plt.hist(runtime_data,bin_nums)
# 设置刻度
x_ticks = [i for i in range(min_runtime,max_runtime+d,d)]
plt.xticks(x_ticks)
# 添加描述
plt.xlabel("Runtime (Minutes)")
plt.ylabel("total numbers")
# 显示
plt.show()
效果图:
rating代码:
import pandas as pdfrom matplotlib import pyplot as plt
# 准备数据
df = pd.read_csv("./IMDB-Movie-Data.csv")
# print(df.head(1))
# print(df.info())
# 提取数据
rating_info = df["Rating"]
data_list = rating_info.values
# 计算最大值和最小值
max_data = data_list.max()
min_data = data_list.min()
# print(max_data,min_data)
# d = 20
# num_bin = (max_data-min_data)//0.5
# 设置不等距离的刻度
num_bin = [1.9,3.5]
i = 3.5
# 循环添加刻度
while i<=9.0:
i += 0.5
num_bin.append(i)
print(num_bin)
# 设置图片大小
plt.figure(figsize=(20,8),dpi=80)
# 画直方图
plt.hist(data_list,num_bin)
# 设置x轴刻度,使其与hist传入的num_bin列表对应
plt.xticks(num_bin)
# 画图
plt.show()
效果图:
- 对于这一组电影数据,如果我们希望统计电影分类(genre)的情况,应该如何处理数据?
- 思路:重新构造一个全为0的数组,列名为分类,如果某一条数据中分类出现过,就让0变为1
代码:
from matplotlib import pyplot as pltimport numpy as np
import pandas as pd
path = "./IMDB-Movie-Data.csv"
# 准备数据
df = pd.read_csv(path)
# print(df["Genre"].head(3))
# 提取
temp_list = df["Genre"].str.split(",").tolist()
# 获取一个含有每种分类的列表
gen_list = list(set([j for i in temp_list for j in i]))
# 构造一个全为0的数组,(colums对应每种分类-上标-列标)
zero_df = pd.DataFrame(np.zeros((df.shape[0],len(gen_list))),columns=gen_list)
# 向数组里面填充数据
for i in range(df.shape[0]):
# zero_df.loc[0,["Sci-fi","Mucical"]] = 1
zero_df.loc[i,temp_list[i]] = 1
# 求出每一列的和(即每一种分类)
toal = zero_df.sum(axis=0)
# 排序
toal = toal.sort_values()
# 设置图片大小
plt.figure(figsize=(20,8),dpi=80)
# 画条形图
plt.bar(range(len(toal)),toal,width=0.3,color="orange")
# 设置x刻度 index返回的是行索引的数组
plt.xticks(range(len(toal)),toal.index)
# 显示图片
plt.show()
效果图: