pandas详解

视频教程

1.pandas的常用数据类型

1.Series 一维,带标签数组

2.DataFrame 二维,Series容器

2.pandas之Series创建

pandas详解

pandas详解

; 3.pandas之Series切片和索引

pandas详解

4.pandas之Series的索引和值

pandas详解

; 5.pandas之读取外部数据

我们的这组数据存在csv中,我们直接使用pd. read_csv即可

和我们想象的有些差别,我们以为他会是一个Series类型,但是他是一个DataFrame,那么接下来我们就来了解这种数据类型

小示例:

现在假设我们有一个组关于狗的名字的统计数据,那么为了观察这组数据的情况,我们应该怎么做呢?

import pandas as pd
df = pd.read_csv('./dogNames2.csv')
print(df)

效果展示

pandas详解

6.pandas之DataFrame

pandas详解

DataFrame对象既有行索引,又有列索引

行索引,表明不同行,横向索引,叫index,0轴,axis=0

列索引,表名不同列,纵向索引,叫columns,1轴,axis=1

pandas详解

pandas详解

那么回到之前我们读取的狗名字统计的数据上,我们尝试一下刚刚的方法

那么问题来了:

很多同学肯定想知道使用次数最高的前几个名字是什么呢?

df.sort_values(by="Count_AnimalName",ascending=*False*)

dataframe排序

import pandas as pd
df = pd.read_csv('./dogNames2.csv')
print(df)
print('*'*100)
print(df.head())
print('*'*100)
print(df.info())
print('*'*100)
print(df.describe())

以Count_AnimalName来排序(默认升序)
df = df.sort_values(by='Count_AnimalName')
ascending=True 为升序,False为倒序
df = df.sort_values(by='Count_AnimalName',ascending=False)
print(df.head(10))

7.pandas之取行或者列

刚刚我们知道了如何给数据按照某一行或者列排序,那么现在我们想单独研究使用次数前100的数据,应该如何做?

df_sorted = df.sort_values(by="Count_AnimalName")

df_sorted[:100]

那么问题来了:

我们具体要选择某一列该怎么选择呢? df[" Count_AnimalName "]

我们要同时选择行和列改怎么办? df[:100][" Count_AnimalName "]

8.pandas之loc

还有更多的经过pandas优化过的选择方式:

1.df.loc 通过 标签索引行数据

2.df.iloc 通过 位置获取行数据

pandas详解

pandas详解

; 9.pandas之布尔索引

回到之前狗的名字的问题上,假如我们想找到所有的使用次数超过800的狗的名字,应该怎么选择?

pandas详解

回到之前狗的名字的问题上,假如我们想找到所有的使用次数超过700并且名字的字符串的长度大于4的狗的名字,应该怎么选择?

pandas详解

10.pandas之字符串方法

pandas详解

; 11.缺失数据的处理

观察下面这组数据

pandas详解

我们的数据缺失通常有两种情况:

一种就是空,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会

示例

假设现在我们有一组从2006年到2016年1000部最流行的电影数据,我们想知道这些电影数据中评分的平均分,导演的人数等信息,我们应该怎么获取?

import pandas as pd, numpy as np
from matplotlib import pyplot as plt

df = pd.read_csv('IMDB-Movie-Data.csv')
print(type(df))
print(df.info())
print(df.head())
print(df['Rating'].values)
print(df['Rating'].describe())
df['Rating'].mean()为numpy类型的数据,不能使用字符串拼接,需要先转换为字符串
电影评分平均值
print('电影平均分:' + str(df['Rating'].mean()))
导演的人数
df['Director'].tolist()  #  python tolist()方法:将数组或者矩阵转换成列表
set(df['Director'].tolist()) # 使用set() 将数组去重并转换为set集合,集合是一个无序的不重复元素序列
print('导演人数:', len(set(df['Director'].tolist())))
别一种方法:df['Director'].unique()可以将df['Director']去重,并返回
print('导演人数:', len(df['Director'].unique()))
由于每一部电影的演员有多人,所以先使用split(',')以逗号分隔,让每组数据的字符串重组为数组
print('所有演员二维数据:')
print(df['Actors'].str.split(',').tolist())
temp_list = df['Actors'].str.split(',').tolist()
将二维数组展开
nums = [i for j in temp_list for i in j]
print('所有演员一维数组:')
print(nums)
数组去重,并取总数
actors = len(set(nums))  # 使用set集合的特点去重
actors2 = len(pd.Series(nums).unique())  # 使用pandas的unique方法去重
print('去重后演员的总人数:', actors, actors2)
电影时长的最大最小值:
max_runtime = df['Runtime (Minutes)'].max()
max_runtime_index = df['Runtime (Minutes)'].argmax()
min_runtime = df['Runtime (Minutes)'].min()
min_runtime_index = df['Runtime (Minutes)'].argmin()
runtime_median = df['Runtime (Minutes)'].median()

pandas详解

示例

对于这一组电影数据,如果我们希望统计电影分类(genre)的情况,应该如何处理数据?

思路:重新构造一个全为0的数组,列名为分类,如果某一条数据中分类出现过,就让0变为1

from matplotlib import pyplot as plt
import numpy as np
import pandas as pd

df = pd.read_csv('IMDB-Movie-Data.csv')
print(df['Genre'])
temp_list = df['Genre'].str.split(',').tolist()
print(temp_list)
利用set展开二维列表并去重
genre_list = list(set([i for j in temp_list for i in j]))
print(genre_list)
构造全为0的DataFrame:df一样的行数,分类总数的列数,索引为分类数据genre_list
np.zeros((a,b))里面传的是元组
zeros_df = pd.DataFrame(np.zeros((df.shape[0], len(genre_list))), columns=genre_list)
print(zeros_df)
for i in range(df.shape[0]):
    zeros_df.loc[i, temp_list[i]] = 1
显示所有列
pd.set_option('display.max_columns', None)
显示所有列
pd.set_option('display.max_columns', None)
#显示所有行
pd.set_option('display.max_rows', None)
#设置value的显示长度为100,默认为50
pd.set_option('max_colwidth',100)
print(zeros_df.head(1))
统计每个分类的电影的数量和
genre_count = zeros_df.sum(axis=0)
print(genre_count)
排序
genre_count = genre_count.sort_values()
画柱状图
_x = genre_count.index
_y = genre_count.values
plt.figure(figsize=(20, 8), dpi=80)
plt.bar(range(len(_x)), _y)
plt.xticks(range(len(_x)), _x)
plt.show()

pandas详解

12.数据合并之join

join:默认情况下他是把行索引相同的数据合并到一起

pandas详解

; 13.数据合并之merge

merge:按照指定的列把数据按照一定的方式合并到一起

pandas详解

示例:

现在我们有一组关于全球星巴克店铺的统计数据,如果我想知道美国的星巴克数量和中国的哪个多,或者我想知道中国每个省份星巴克的数量的情况,那么应该怎么办?

import numpy as np
import pandas as pd

df = pd.read_csv('starbucks_store_worldwide.csv')
print(df)
print(df.info())
df_country = df.groupby('Country')  # 生成一个DataFrameGroupBy object
print(df_country)
# 显示所有列
pd.set_option('display.max_columns', None)
# 遍历
# for i in df_country:
#     print(i) # 遍历后的每一个数据都是一个元组
#
# 由于遍历后的每一个值都是元组,所以还可以这样遍历
for i, j in df_country:
    print(i, j, type(j))  # i为国家信息,j为一个DataFrame,其中所有的country字段均为i
    print('*' * 100)
#
# 调用聚合方法
print(df_country.count())  # count()可以统计每个字段的总数
print(df_country['City'].count())  # 单独统计一个字段的总数
#
"""
平均值,中位数等方法也可以使用,但这里使用没有意义,因为都是字符串
count:分组中非NA值的数量
sum:非NA的和
mean:非NA值的平均值
median:非NA值的算术中位数
std、var: 无偏(分母为n-a)标准差和方差
min,max:非NA值的最小值和最大值 """
country_count = df_country['City'].count()
# 美国和中国的星巴克店铺数量
print('美国:', country_count['US'])
print('中国:', country_count['CN'])

统计中国每个省份的星巴克
china_data = df[df['Country'] == 'CN']  # 取出中国的星巴克数据,这里可以不需要分组,直接取数据
print(china_data)
print(china_data.info())
province_data = china_data.groupby('State/Province').count()['Brand']
print(province_data)
groupby可以传入多个条件来分组
print(df['Brand'])
china_data_group = df.groupby(
    by=[df['Country'], df['State/Province']]).count()  # 返回一个Series,列索引有两个,一个是country,一个是State/Province
print(china_data_group)
print(china_data_group['Brand'])

以下三种写法,结果相同
group1 = df.groupby(by=[df['Country'], df['State/Province']]).count()['Brand']
group2 = df['Brand'].groupby(by=[df['Country'], df['State/Province']]).count()
group3 = df.groupby(by=[df['Country'], df['State/Province']])['Brand'].count()
print(group1, type(group1))
print('*' * 100)
print(group2, type(group2))
print('*' * 100)
print(group3, type(group3))
取值可以为DataFrame,需要使用一个小技巧
group4 = df[['Brand']].groupby(by=[df['Country'], df['State/Province']]).count()
print('*' * 100)
print(group4, type(group4))
print(group1.index)

14.分组和聚合

grouped = df.groupby(by="columns_name")

grouped是一个DataFrameGroupBy对象,是可迭代的

grouped中的每一个元素是一个元组

元组里面是(索引(分组的值),分组之后的DataFrame)

DataFrameGroupBy对象有很多经过优化的方法

pandas详解

如果我们需要对国家和省份进行分组统计,应该怎么操作呢?

grouped = df.groupby(by=[df["Country"],df["State/Province"]])

很多时候我们只希望对获取分组之后的某一部分数据,或者说我们只希望对某几列数据进行分组,这个时候我们应该怎么办呢?

获取分组之后的某一部分数据:

df.groupby(by=["Country","State/Province"])["Country"].count()

对某几列数据进行分组:

df["Country"].groupby(by=[df["Country"],df["State/Province"]]).count()

观察结果,由于只选择了一列数据,所以结果是一个Series类型

如果我想返回一个DataFrame类型呢?

t1 = df[["Country"]].groupby(by=[df["Country"],df["State/Province"]]).count()
t2 = df.groupby(by=["Country","State/Province"])[["Country"]].count()

以上的两条命令结果一样

和之前的结果的区别在于当前返回的是一个DataFrame类型

简单的索引操作:

•获取index: df.index

•指定index : df.index = ['x','y']

•重新设置index : df.reindex(list("abcedf"))

•指定某一列作为index : df.set_index("Country",drop=False)

•返回index的唯一值: df.set_index("Country").index.unique()

; 15.Series复合索引

pandas详解

pandas详解

pandas详解

示例

现在我们有2015到2017年25万条911的紧急电话的数据,请统计出出这些数据中不同类型的紧急情况的次数,如果我们还想统计出不同月份不同类型紧急电话的次数的变化情况,应该怎么做呢?

import pandas as pd, numpy as np
from matplotlib import pyplot as plt

df = pd.read_csv('911.csv')
显示所有列
pd.set_option('display.max_columns', None)
print(df.head())
print(df.info())
print(df['title'].str.split(':'))
print(df['title'].str.split(':')[0]) # 不能取到数据
to_list()将序列转换为数组
temp_list = df['title'].str.split(':').to_list()
temp_list = df['title'].str.split(':').tolist()
print(temp_list)
遍历并取出第一项数据并去重
cate_list = list(set([i[0] for i in temp_list]))
print(cate_list)
构造一个DataFrame,三列,与df同行,数据全为0
zeros_df = pd.DataFrame(np.zeros((df.shape[0], len(cate_list))), columns=cate_list)
print(zeros_df)
 由于df数据量太大,如果直接遍历,会消耗很长时间
for i in range(df.shape[0]):
    zeros_df.loc[i,temp_list[i][0]] = 1
#
print(zeros_df)

遍历cate_list,只需要循环三次
for cate in cate_list:
    # df['title'].str.contains(cate)返回的是一个布尔型数组,行数与zeros_df相同,列数为三列,
    # 包含cate的那一列为True,具体可见5.62布尔索引章节
    zeros_df[cate][df['title'].str.contains(cate)] = 1

print(zeros_df)

统计邮寄类型的数量
sum_ret = zeros_df.sum(axis=0)
print(sum_ret)
import pandas as pd, numpy as np
from matplotlib import pyplot as plt

df = pd.read_csv('911.csv')
#显示所有行
pd.set_option('display.max_rows', None)
print(df.head())
print(df.info())

to_list()将序列转换为数组
temp_list = df['title'].str.split(':').to_list()

print(temp_list)
遍历并取出第一项的分类
cate_list = [i[0] for i in temp_list]
print(cate_list)
cate_df = pd.DataFrame(np.array(cate_list).reshape((df.shape[0]), 1), columns=['cate'])
print(cate_df)
添加一列,列索引为cate
df['cate'] = cate_df
print(df['cate'])
print(df.groupby(by='cate').count()['title'])

16.pandas中的时间序列

生成一段时间范围

pd.date_range(start=None, end=None, periods=None, freq='D')

start和end以及freq配合能够生成start和end范围内以频率freq的一组时间索引

start和periods以及freq配合能够生成从start开始的频率为freq的periods个时间索引

pandas详解

关于频率的更多缩写

pandas详解

在DataFrame中使用时间序列

index=pd.date_range("20170101",periods=10)

df = pd.DataFrame(np.random.rand(10),index=index)

回到最开始的911数据的案例中,我们可以使用pandas提供的方法把时间字符串转化为时间序列

df["timeStamp"] = pd.to_datetime(df["timeStamp"],format="")

format参数大部分情况下可以不用写,但是对于pandas无法格式化的时间字符串,我们可以使用该参数,比如包含中文

那么问题来了:

我们现在要统计每个月或者每个季度的次数怎么办呢?

from matplotlib import pyplot as plt
import pandas as pd
df = pd.read_csv('911.csv')
#显示所有列
pd.set_option('display.max_columns', None)
#显示所有行
pd.set_option('display.max_rows', None)
print(df.info())
print(df.head())
将时间字符串转换为时间类型数据datetime64,以便进一步处理
print(pd.to_datetime(df['timeStamp']).head())
重新赋值df['timeStamp']
df['timeStamp'] = pd.to_datetime(df['timeStamp'])
将列timeStamp转换为行索引
df.set_index('timeStamp',inplace=True)
print(df.head())

统计出911数据中不同月份电话次数
count_by_month = df.resample('M').count()['title']
print(count_by_month)

_x = count_by_month.index
_y = count_by_month.values
print(_x)
print(_y)
_x = [i.strftime('%Y%m%d') for i in _x]
plt.figure(figsize=(20,8), dpi=80)
plt.plot(_x,_y)
plt.plot(range(len(_x)),_y)
plt.xticks(_x,rotation=45)
plt.show()

17.pandas重采样

pandas详解

示例

1.统计出911数据中不同月份电话次数的变化情况

2.统计出911数据中不同月份不同类型的电话的次数的变化情况

from matplotlib import pyplot as plt
import pandas as pd,numpy as np
df = pd.read_csv('911.csv')
重新赋值df['timeStamp']
df['timeStamp'] = pd.to_datetime(df['timeStamp'])
#添加列,表示分类
temp_list = df["title"].str.split(": ").tolist()
cate_list = [i[0] for i in temp_list]
创建列
df["cate"] = pd.DataFrame(np.array(cate_list).reshape((df.shape[0],1)))
将时间列转化为索引
df.set_index("timeStamp",inplace=True)
print(df.head(1))
dk = df.groupby('cate')
print(dk)
plt.figure(figsize=(20, 8), dpi=80)
for group_name,group_data in dk:
    print(group_name,group_data)
    # 对不同的分类都进行绘图
    count_by_month = group_data.resample("M").count()["title"]
    # 画图
    _x = count_by_month.index
    print(_x)
    _y = count_by_month.values
    print(_y)
    _x = [i.strftime("%Y%m%d") for i in _x]

    plt.plot(range(len(_x)), _y, label=group_name)

plt.xticks(range(len(_x)), _x, rotation=45)
plt.legend(loc="best")
plt.show()

现在我们有北上广、深圳、和沈阳5个城市空气质量数据,请绘制出5个城市的PM2.5随时间的变化情况

coding=utf-8
import pandas as pd
from matplotlib import pyplot as plt

file_path = "./PM2.5/BeijingPM20100101_20151231.csv"

df = pd.read_csv(file_path)
print(df.head())
print(df.info())
把分开的时间字符串通过periodIndex的方法转化为pandas的时间类型
period = pd.PeriodIndex(year=df["year"], month=df["month"], day=df["day"], hour=df["hour"], freq="H")
增加一列df["datetime"]
df["datetime"] = period
print(df.head(10))
#
把datetime 设置为索引
df.set_index("datetime", inplace=True)
#
进行降采样,如果按日来排序,数据图不好看,按月份太稀疏,按日太绸
df = df.resample("7D").mean()
print(df.head())
处理缺失数据,删除缺失数据
print(df["PM_US Post"])
dropna()该函数主要用于滤除缺失数据。
如果是Series,则返回一个仅含非空数据和索引值的Series,默认丢弃含有缺失值的行。
美国数据
data = df["PM_US Post"].dropna()  # 使用降采样后,会计算均值,这里再使用dropna()过滤空值意义不大
中国数据
data_china = df["PM_Nongzhanguan"]

print(data_china.head(100))
#画图

_x = data.index
_x = [i.strftime("%Y%m%d") for i in _x]
取中国PM2.5数据
_x_china = [i.strftime("%Y%m%d") for i in data_china.index]
print(len(_x_china),len(_x_china))
_y = data.values
_y_china = data_china.values

plt.figure(figsize=(20,8),dpi=80)

plt.plot(range(len(_x)),_y,label="US_POST",alpha=0.7)
plt.plot(range(len(_x_china)),_y_china,label="CN_POST",alpha=0.7)

plt.xticks(range(0,len(_x_china),10),list(_x_china)[::10],rotation=45)

plt.legend(loc="best")

plt.show()

Original: https://blog.csdn.net/qq_59084325/article/details/126181015
Author: BillySturate
Title: pandas详解

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/753560/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球