0
点赞
收藏
分享

微信扫一扫

数据分析之pandas模块的使用(一)

什么是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 pd

In [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]: t
Out[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.index
Out[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),Metascore
1,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 pd

path = "./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 pd
from 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()

效果图:

数据分析之pandas模块的使用(一)_大数据

rating代码:

import pandas as pd
from 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()

效果图:

数据分析之pandas模块的使用(一)_大数据_02

  • 对于这一组电影数据,如果我们希望统计电影分类(genre)的情况,应该如何处理数据?
  • 思路:重新构造一个全为0的数组,列名为分类,如果某一条数据中分类出现过,就让0变为1

代码:

from matplotlib import pyplot as plt
import 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()

效果图:

数据分析之pandas模块的使用(一)_python_03


举报

相关推荐

0 条评论