数据分析之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()

效果图:

在这里插入图片描述

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()

效果图:

在这里插入图片描述

  • 对于这一组电影数据,如果我们希望统计电影分类(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()

效果图:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46456049/article/details/108919194