Bootstrap

从零开始学Pandas:数据分析必备技能速成

从零开始学Pandas:数据分析必备技能速成

  • 1. 创建pandas对象
    • 1.1 前言
    • 1.2 使用DataFrame类创建pandas对象
    • 1.3 对DataFrame对象进行索引
    • 1.4 使用Series类创建pandas对象
    • 1.5 对DataFrame Series对象使用常见方法
  • 2. pandas读取文件
    • 2.1 使用pd.read_*方法读取文件
    • 2.2 使用to_*保存数据
    • 2.3 使用info()方法查看详细信息
  • 3. 创建DataFrame子集
    • 3.1 导入数据
    • 3.2 使用索引DataFrame创建子集
    • 3.3 筛选
    • 3.4 loc和iloc选择特定行列
  • 4. 使用matplotlib画图
    • 4.1 导入数据
    • 4.2 .plot()使用
    • 4.3 subplot子图绘画
    • 4.4 保存图片
  • 5. 创建新列
    • 5.1 导入数据
    • 5.2 创建新列
    • 5.3 列名重命名
  • 6. 汇总统计
    • 6.1 导入数据
    • 6.2 Series对象数据汇总
    • 6.3 DataFrame对象数据汇总
    • 6.4 分组
    • 6.5 分组索引
    • 6.6 统计数据
  • 7. 重塑表格布局
    • 7.1 导入数据
    • 7.2 排序
    • 7.3 数据重塑
    • 7.4 数据重塑 聚合
    • 7.5 添加新索引
    • 7.6 将宽表变长表
  • 8. 合并多个表
    • 8.1 导入数据
    • 8.2 拼接
  • 9. 处理时间序列数据
    • 9.1 导入数据
    • 9.2 时间字符串to时间数据
    • 9.3 日期时间常用方法
    • 9.4 根据日期时间画图
    • 9.5 日期时间索引
    • 9.6 按照时间频率分组聚合
  • 10. 操作文本数据
    • 10.1 导入数据
    • 10.2 字符串基本操作

)
pandas代码和CSV文件 点击免费下载

1. 创建pandas对象

1.1 前言

在 Pandas 中,SeriesDataFrame 是核心数据结构。Series 是一维数组,包含数据和索引,适合存储单列数据,如数值或字符串。DataFrame 是二维表格,由多个 Series 组成,每列是一个 Series,具有共享的行索引,适合处理多列数据,如表格或数据库结构。
两者的关系为:DataFrameSeries 的集合,每列都是一个 Series 对象。例如,DataFrame 中可以通过列名提取 Series,也可以将多个 Series 合并成一个 DataFrame。因此,Series 是构成 DataFrame 的基础。

1.2 使用DataFrame类创建pandas对象

import pandas as pd
df = pd.DataFrame(  #参数为字典,键为标题,值为数据且用列表
    {
        "Name":[
            "Braund, Mr. Owen Harris",
            "Allen, Mr. William Henry",
            "Bonnell, Miss. Elizabeth",
        ],
        "Age":[22, 35, 58],
        "Sex":["male", "male", "female"],
    }
)
df #查看对象
NameAgeSex
0Braund, Mr. Owen Harris22male
1Allen, Mr. William Henry35male
2Bonnell, Miss. Elizabeth58female

1.3 对DataFrame对象进行索引

df["Age"] #对Age索引
022
135
258
Name:Agedtype:int64

1.4 使用Series类创建pandas对象

ages = pd.Series([22, 35, 58], name="Age") #创建Series对象
ages #查看ages
022
135
258
Name:Agedtype:int64

1.5 对DataFrame Series对象使用常见方法

df["Age"].max()
# np.int64(58)
ages.max()
# np.int64(58)
df.describe() #对DataFrame中数值型的列可以详细描述出来 例如数量 平均值等
Age
count3.000000
mean38.333333
std18.230012
min22.000000
25%28.500000
50%35.000000
75%46.500000
max58.000000

2. pandas读取文件

2.1 使用pd.read_*方法读取文件

import pandas as pd #导入pandas包
titanic = pd.read_csv("train.csv") #读取csv文件 
titanic #查看文件

在这里插入图片描述

titanic.head(8) #查看前8行

在这里插入图片描述

titanic.dtypes #查看每一列的数据类型

在这里插入图片描述

2.2 使用to_*保存数据

# 将titanic数据保存为excel形式 sheet_name为passengers 不添加索引到表格里
titanic.to_excel("titanic.xlsx", sheet_name="passengers", index=False)

在这里插入图片描述

#重新读取保存文件
titanic = pd.read_excel("titanic.xlsx", sheet_name="passengers")
titanic.head() #查看前5行数据

在这里插入图片描述

2.3 使用info()方法查看详细信息

titanic.info() #查看详细信息

在这里插入图片描述

DataFrame类
共891行 索引从0到890
数据共12列
每列的索引 Column 每列的名字 Non-Null Count 每列含有数据的数量(有的列为NAN) Dtype 每列数据类型
dtypes 数据类型总结
memory usage 使用内存大小

3. 创建DataFrame子集

3.1 导入数据

import pandas as pd
titanic = pd.read_csv("train.csv")
titanic.head() #查看前5行数据

在这里插入图片描述

3.2 使用索引DataFrame创建子集

ages = titanic["Age"] #单列创建Series对象
age_sex = titanic[["Age", "Sex"]] #多列创建DataFrame对象
type(titanic["Age"]), type(titanic[["Age", "Sex"]]) #查看对象类型
# (pandas.core.series.Series, pandas.core.frame.DataFrame)
ages.head(), age_sex.head() #查看数据

在这里插入图片描述

titanic["Age"].shape, titanic[["Age", "Sex"]].shape #查看数据形状
# ((891,), (891, 2))

3.3 筛选

#筛选条件
titanic["Age"] > 35 

在这里插入图片描述

# format: DataFrameobject[筛选条件]
above_35 = titanic[titanic["Age"] > 35] #选择Age大于35的行
above_35.head()

在这里插入图片描述

#选择2 3等舱的行 .isin()方法
class_23 = titanic[titanic["Pclass"].isin([2, 3])]
class_23.head()

在这里插入图片描述

#选择Age列有数值的行 .notna()方法
age_no_na = titanic[titanic["Age"].notna()]
age_no_na.head()

在这里插入图片描述

3.4 loc和iloc选择特定行列

# format: DataFrameobject.loc[筛选条件, "列名"]
# 筛选年龄大于35的行,并只显示名字 Series类型
adult_names = titanic.loc[titanic["Age"] > 35, "Name"]
adult_names.head()

在这里插入图片描述

#format: DataFrameobject.iloc[行切片, 列切片]
titanic.iloc[9:25, 2:5] #10到25行,3到5列

在这里插入图片描述

4. 使用matplotlib画图

4.1 导入数据

import pandas as pd
import matplotlib.pyplot as plt
# index_col=0 csv文件第一列将作为DataFrame的索引 parse_dates=True 将被选为索引的列(或自动识别的日期列)转换为日期时间格式,而不是保留为字符串。
air_quality = pd.read_csv("air_quality_no2.csv", index_col=0, parse_dates=True)
# 查看数据
air_quality.head()

在这里插入图片描述

4.2 .plot()使用

air_quality.plot() #直接绘画 第一列索引为x轴 各列为y轴
plt.show()

在这里插入图片描述

#format: DataFrameObject["列名"].plot()
#只画"station_paris"列
air_quality["station_paris"].plot()
plt.show()

在这里插入图片描述

#画其他类型的图 
#format: DataFrameObject.plot.other()
#画散点图
air_quality.plot.scatter(x="station_london", y="station_paris", alpha=0.5)
plt.show()

在这里插入图片描述

air_quality.plot.box()

在这里插入图片描述

[                          
    method_name
    for method_name in dir(air_quality.plot)
    if not method_name.startswith("_")
]                #查看能画哪些图类型
#['area',
 #'bar',
 #'barh',
 #'box',
 #'density',
 #'hexbin',
 #'hist',
 #'kde',
 #'line',
 #'pie',
# 'scatter']

4.3 subplot子图绘画

#format: DataFrame.plot.area(figsize=(x, y), subplot=True)
axs = air_quality.plot.area(figsize=(12, 4), subplot=True)

在这里插入图片描述

4.4 保存图片

# 使用 Matplotlib 和 Pandas 的绘图功能来创建和保存一张面积图

# 创建一个图表和子图(即坐标轴)
# fig 是图形对象,可以用于控制整体的图表布局和保存
# axs 是坐标轴对象,用于在图中绘制数据
# figsize=(12, 4) 设置图表的宽度为 12 英寸,高度为 4 英寸,控制图表的整体尺寸。
fig, axs = plt.subplots(figsize=(12, 4))
# 调用 Pandas 的 plot.area() 方法在 axs 上绘制面积图
# air_quality 是一个 DataFrame,其中包含需要绘制的 NO₂(氮氧化物)浓度数据
# ax=axs 指定在 axs 这个坐标轴上绘制图形,而不是创建新的坐标轴
air_quality.plot.area(ax=axs)
# 设置y轴标签
axs.set_ylabel("NO$_2$ concentration")
# 将绘制的图保存为一个 PNG 文件
fig.savefig("no2_concentrations.png")
# 显示图片
plt.show()

在这里插入图片描述

5. 创建新列

5.1 导入数据

import pandas as pd
# index_col=0 csv文件第一列将作为DataFrame的索引 parse_dates=True 将被选为索引的列(或自动识别的日期列)转换为日期时间格式,而不是保留为字符串。
air_quality = pd.read_csv("air_quality_no2.csv", index_col=0, parse_dates=True)
# 查看数据
air_quality.head()

在这里插入图片描述

5.2 创建新列

# format: DataFrameObject["新列名"] = DataFrameObject["原列名"] + - * / value
air_quality["london_mg_per_cubic"] = air_quality["station_london"] * 1.882
air_quality.head()

在这里插入图片描述

air_quality["ratio_paris_antwerp"] = (
    air_quality["station_paris"] / air_quality["station_antwerp"]
)
air_quality.head()

在这里插入图片描述

5.3 列名重命名

#使用 .rename(columns=)方法
#formated: DataFrameObject.rename(columns={字典}) 字典的键为原列名 值为新列名
air_quality_renamed = air_quality.rename(
    columns={
        "station_antwerp": "BETR801",
        "station_paris": "FR04014",
        "station_london": "London Westminster",
    }
)
air_quality_renamed.head()

在这里插入图片描述

6. 汇总统计

6.1 导入数据

import pandas as pd
titanic = pd.read_csv("titanic.csv")
titanic.head()

在这里插入图片描述

6.2 Series对象数据汇总

# 方法:.mean() .max() .min() .median() .count()
titanic["Age"].mean() 
# np.float64(29.69911764705882)

6.3 DataFrame对象数据汇总

# 方法:.mean() .max() .min() .median() .count()
titanic[["Age", "Fare"]].median() 
#Age     28.0000
#Fare    14.4542
#dtype: float64
titanic[["Age", "Fare"]].describe()

在这里插入图片描述

# 使用agg指定汇总参数 
# format: DataFrame.agg(字典)
titanic.agg(
    {
        "Age": ["min", "max", "median", "skew"],
        "Fare": ["min", "max", "median", "mean"]
    }
)

在这里插入图片描述

6.4 分组

# 按照Sex的不同类别分组 并且取Age列的平均值
# format: DataFrame.groupby("列名").mean()
titanic[["Sex", "Age"]].groupby("Sex").mean()

在这里插入图片描述

# 按照Sex的不同类别分组 并且取数值列的平均值  numeric_only=True 只计算数值类型的列
titanic.groupby("Sex").mean(numeric_only=True)

在这里插入图片描述

6.5 分组索引

#索引分组后Age列的平均值
titanic.groupby("Sex")["Age"].mean()
#Sex
#female    27.915709
#male      30.726645
#Name: Age, dtype: float64
#按照"Sex" "Pclass"列分组后 取"Fare"的平均值
titanic.groupby(["Sex", "Pclass"])["Fare"].mean()
#Sex     Pclass
#female  1         106.125798
#        2          21.970121
#        3          16.118810
#male    1          67.226127
#        2          19.741782
#        3          12.661633
#Name: Fare, dtype: float64

6.6 统计数据

#使用.value_counts() 统计每个类别的数量
#format: SeriesObject.value_count()
titanic["Pclass"].value_counts()
#Pclass
#3    491
#1    216
#2    184
#Name: count, dtype: int64
#分组后统计
titanic.groupby("Pclass")["Pclass"].count()
#Pclass
#1    216
#2    184
#3    491
#Name: Pclass, dtype: int64

7. 重塑表格布局

7.1 导入数据

import pandas as pd
titanic = pd.read_csv("titanic.csv")
titanic.head()

在这里插入图片描述

air_quality = pd.read_csv(
    "air_quality_long.csv", index_col="date.utc", parse_dates=True
)
air_quality.head()

在这里插入图片描述

7.2 排序

# 方法.sort_values(by="列名") 按照"Age"升序排列
titanic.sort_values(by="Age").head()

在这里插入图片描述

# 按照"Pclass" "Age"降序排列
titanic.sort_values(by=['Pclass', 'Age'], ascending=False).head()

在这里插入图片描述

# 筛选"parameter"=="no2"的行
no2 = air_quality[air_quality["parameter"] == "no2"]
# 按照索引排序 并且按照location分组 每组取前面两行
no2_subset = no2.sort_index().groupby(["location"]).head(2)
# 展示数据
no2_subset

在这里插入图片描述

7.3 数据重塑

# 重新构造 标题为"location"列各个类别 值为"value"对应的数值
no2_subset.pivot(columns="location", values="value")

在这里插入图片描述

no2.head()

在这里插入图片描述

# 重新构造一个DataFrame 重新构造 标题为"location"列各个类别 值为"value"对应的数值 
# 使用.plot()方法画图 x为时间轴索引 y为各列
no2.pivot(columns="location", values="value").plot()

在这里插入图片描述

7.4 数据重塑 聚合

# .pivot_table()方法对重新塑造的数据聚合
# 索引列"location" 标题行"parameter" 值"value"列 聚合方法"mean"求平均
air_quality.pivot_table(
    values="value", index="location", columns="parameter", aggfunc="mean"
)

在这里插入图片描述

air_quality.pivot_table(
    values="value",
    index="location",
    columns="parameter",
    aggfunc="mean",
    margins=True,
)

在这里插入图片描述

7.5 添加新索引

no2_pivoted = no2.pivot(columns="location", values="value")
no2_pivoted.head()

在这里插入图片描述

# 使用.reset_index() 添加新索引
no2_pivoted = no2.pivot(columns="location", values="value").reset_index()
no2_pivoted.head()

在这里插入图片描述

7.6 将宽表变长表

# 使用.melt()方法 该方法会将 id_vars 中未提及的所有列一起熔化为两列:一列包含列标题名称,一列包含值本身。默认情况下,后一列取"value"名
no_2 = no2_pivoted.melt(id_vars="date.utc")
no_2.head()

在这里插入图片描述

# 指定 date.utc 列作为标识变量。这意味着在转换过程中,date.utc 列的值将保留,不会被改变
# value_vars=["BETR801", "FR04014", "London Westminster"]:指定需要变形的值变量。这些列(BETR801、FR04014 和 London Westminster)的值将被收集到新列中
# value_name="NO_2":指定新列的名称为 NO_2,该列将包含从 value_vars 列中收集到的所有数值
# var_name="id_location":指定新列的名称为 id_location,该列将包含原来被变形的列名(即 BETR801、FR04014 和 London Westminster)的名称
no_2 = no2_pivoted.melt(
    id_vars="date.utc",  
    value_vars=["BETR801", "FR04014", "London Westminster"],
    value_name="NO_2",
    var_name="id_location"
)
no_2.head()

在这里插入图片描述

8. 合并多个表

8.1 导入数据

import pandas as pd
air_quality_no2 = pd.read_csv("air_quality_no2_long.csv", 
                             parse_dates=True)
air_quality_no2 = air_quality_no2[["date.utc", "location",
                                   "parameter", "value"]
air_quality_no2.head()

在这里插入图片描述

air_quality_pm25 = pd.read_csv("air_quality_pm25_long.csv",
                              parse_dates=True)
air_quality_pm25 = air_quality_pm25[["date.utc", "location",
                                    "parameter", "value"]]
air_quality_pm25.head()

37

8.2 拼接

# 使用pd.concat()方法拼接两个表 
# 参数1 拼接列表 参数2 沿哪个轴
air_quality = pd.concat([air_quality_pm25, air_quality_no2], axis=0)
air_quality.head()

38

# 通过 keys 参数提供了一个方便的解决方案,添加了一个额外的(分层的)行索引
air_quality_ = pd.concat([air_quality_pm25, air_quality_no2], keys=["PM25", "NO2"])
air_quality_

39

9. 处理时间序列数据

9.1 导入数据

import pandas as pd
import matplotlib.pyplot as plt
air_quality = pd.read_csv("air_quality_no2_long.csv")
air_quality = air_quality.rename(columns={"date.utc": "datetime"})
air_quality.head()

40

# air_quality.city:通过 属性 的方式访问列。这种方式更简洁,但仅适用于列名符合变量命名规则的情况(例如,列名不能包含空格、特殊字符,且不能以数字开头)
# air_quality["city"]:通过 索引 的方式访问列。该方法通用且更可靠,适用于所有列名
air_quality.city.unique()
# array(['Paris', 'Antwerpen', 'London'], dtype=object)

9.2 时间字符串to时间数据

# 通过应用 to_datetime 函数,pandas 会解释字符串并将其转换为日期时间(即 datetime64[ns, UTC])对象
air_quality["datetime"] = pd.to_datetime(air_quality["datetime"])
air_quality["datetime"]air_quality["datetime"]

41

9.3 日期时间常用方法

air_quality["datetime"].min(), air_quality["datetime"].max()
#(Timestamp('2019-05-07 01:00:00+0000', tz='UTC'),
# Timestamp('2019-06-21 00:00:00+0000', tz='UTC'))
air_quality["datetime"].max() - air_quality["datetime"].min()
# Timedelta('44 days 23:00:00')
# 通过使用 Timestamp 对象进行日期,pandas 提供了许多与时间相关的属性。例如,月份,但也包括年份、季度,...所有这些属性都可以由 dt 访问器访问。
air_quality["month"] = air_quality["datetime"].dt.month
air_quality.head()

42

# 按照星期日 "location"分组 求"value"列平均值
air_quality.groupby(
    [air_quality["datetime"].dt.weekday, "location"])["value"].mean()

43

9.4 根据日期时间画图

# plt.subplots():创建一个图形(figure)和一个或多个子图(axes)。在这里,它创建了一个包含一个子图的图形
# figsize=(12, 4):设置图形的大小,宽度为 12 英寸,高度为 4 英寸。这个参数控制了图表的显示尺寸
fig, axs = plt.subplots(figsize=(12, 4))
# air_quality["datetime"].dt.hour:从 datetime 列中提取小时信息(.dt.hour),按小时对数据进行分组
# ["value"]:指定要对其计算均值的列为 value 列
# .mean():计算每小时的 value 列的平均值
# .plot(kind='bar', rot=0, ax=axs)
# kind='bar':指定图表类型为柱状图(bar chart)
# rot=0:设置 x 轴标签的旋转角度为 0,即标签保持水平显示
# ax=axs:指定绘图的轴(axes)对象为 axs,即将图表绘制在之前创建的 axs 子图中
air_quality.groupby(air_quality["datetime"].dt.hour)["value"].mean().plot(
    kind='bar', rot=0, ax=axs
)
# 设置 x 轴的标签
plt.xlabel("Hour of the day")
# 设置 y 轴的标签
plt.ylabel("$NO_2 (ug/m^3)$")
# 展示
plt.show()

d7

9.5 日期时间索引

# 通过.pivot方法重塑 设置索引为datetime
no_2 = air_quality.pivot(index="datetime", columns="location", values="value")
no_2.head()

44

# 索引年 索引周
no_2.index.year, no_2.index.weekday
#(Index([2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019,
#       ...
#       2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019],
#       dtype='int32', name='datetime', length=1033),
#Index([1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
#       ...
#       3, 3, 3, 3, 3, 3, 3, 3, 3, 4],
#      dtype='int32', name='datetime', length=1033))
# 索引切片绘图
no_2["2019-05-20": "2019-05-21"].plot()

d7

9.6 按照时间频率分组聚合

# resample 是 Pandas 中用于重采样时间序列数据的方法
# "ME" 表示重采样的频率。"ME" 代表 月末(Month End),即按每个月的最后一天作为时间间隔
# 这一步将 no_2 中的数据重新按月进行分组,每个组包含该月内的数据
# 在分组完成后,.max() 会对每组数据(即每个月的数据)取最大值
# monthly_max 是结果保存的变量名称。它存储的是 no_2 DataFrame 按月重采样后的最大值
monthly_max = no_2.resample("ME").max()
monthly_max

45

# monthly_max.index.freq 用于查看 monthly_max DataFrame 索引的频率属性
monthly_max.index.freq
# <MonthEnd>
# no_2.resample("D").mean().plot(style="-o", figsize=(10, 5)) 这段代码用于对 no_2 数据按天进行重采样,计算每天的均值,并以折线图的方式绘制结果
# style="-o":指定绘图的样式 figsize=(10, 5):设置图表的大小,宽度为 10 英寸,高度为 5 英寸
no_2.resample("D").mean().plot(style="-o", figsize=(10, 5))

在这里插入图片描述

10. 操作文本数据

10.1 导入数据

import pandas as pd
titanic = pd.read_csv("titanic.csv")
titanic.head()

46

10.2 字符串基本操作

# 要将 Name 列中的每个字符串设置为小写,请选择 Name 列,添加 str 访问器并应用 lower 方法
titanic["Name"].str.lower()
#0                                braund, mr. owen harris
#1      cumings, mrs. john bradley (florence briggs th...
#2                                 heikkinen, miss. laina
#3           futrelle, mrs. jacques heath (lily may peel)
#4                               allen, mr. william henry
#                             ...                        
#886                                montvila, rev. juozas
#887                         graham, miss. margaret edith
#888             johnston, miss. catherine helen "carrie"
#889                                behr, mr. karl howell
#890                                  dooley, mr. patrick
#Name: Name, Length: 891, dtype: object
# "Name"列 在 , 分离 
titanic["Name"].str.split(",")
#0                             [Braund,  Mr. Owen Harris]
#1      [Cumings,  Mrs. John Bradley (Florence Briggs ...
#2                              [Heikkinen,  Miss. Laina]
#3        [Futrelle,  Mrs. Jacques Heath (Lily May Peel)]
#4                            [Allen,  Mr. William Henry]
#                             ...                        
#886                             [Montvila,  Rev. Juozas]
#887                      [Graham,  Miss. Margaret Edith]
#888          [Johnston,  Miss. Catherine Helen "Carrie"]
#889                             [Behr,  Mr. Karl Howell]
#890                               [Dooley,  Mr. Patrick]
#Name: Name, Length: 891, dtype: object
# 取分类后列表的第一位元素
titanic["Surname"] = titanic["Name"].str.split(",").str.get(0)
#0         Braund
#1        Cumings
#2      Heikkinen
#3       Futrelle
#4          Allen
#         ...    
#886     Montvila
#887       Graham
#888     Johnston
#889         Behr
#890       Dooley
#Name: Surname, Length: 891, dtype: object
#筛选"Name"列中字符串里面有没有"Countess"字符串
titanic["Name"].str.contains("Countess")
#0      False
#1      False
#2      False
#3      False
#4      False
#       ...  
#886    False
#887    False
#888    False
#889    False
#890    False
#Name: Name, Length: 891, dtype: bool
#查看筛选出来的行
titanic[titanic["Name"].str.contains("Countess")]

47

# 查看字符串长度
titanic["Name"].str.len()
#0      23
#1      51
#2      22
#3      44
#4      24
#       ..
#886    21
#887    28
#888    40
#889    21
#890    19
#Name: Name, Length: 891, dtype: int64
# 找到 titanic DataFrame 中 Name 列中名字字符数最长的那一行的索引
titanic["Name"].str.len().idxmax()
# 307
# 找出那行名字
titanic.loc[titanic["Name"].str.len().idxmax(), "Name"]
# 字符串名称替换
titanic["Sex_short"] = titanic["Sex"].replace({"male": "M", "female": "F"})
titanic["Sex_short"]
#0      M
#1      F
#2      F
#3      F
#4      M
#      ..
#886    M
#887    F
#888    F
#889    M
#890    M
#Name: Sex_short, Length: 891, dtype: object
;