Skip to content

Pandas​ 📦


  • 表数据处理神器 -- Pandas

Pandas 是 Python 进行数据分析的基础包,基于 NumPy 构建,

该工具是为了解决数据分析任务而创建的。

Pandas 的名称来自于面板数据( panel data )和python数据分析( data analysis )。

Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的函数和方法,

能使我们快速便捷地处理数据。这也是使 Python 成为强大而高效的数据分析环境的重要因素之一。



一、读取外部数据

在数据科学领域,Python可以完成很多不同的任务,

如数据分析、数据可视化、数据挖掘、机器学习、深度学习等,

而这些任务都是针对同一个对象——数据。所以,对于数据分析师来说,

学习Python最重要的一个知识点就是如何将外部数据读取到Python当中。

只有数据导进来了,之后才有可能使用Python对数据进行一系列的处理,比如:

  • 数据探索( 如导入数据集的形状、简单描述统计 );
  • 数据清洗( 如数据类型的转换、缺失值/异常值/重复值的处理、文本数据的处理 );
  • 数据汇总( 如数据合并、分组聚合运算、透视表的使用 )等。

首先需要将 pandas 这个模块导入:

python
# 约定俗成的导入方式:
import numpy as np
import pandas as pd
python
# 查看版本
pd.__version__

# '2.2.2'
  • 文本文件的读取

对于 csv 或者 txt 后缀的文本文件,可以使用pandas模块中的read_csv函数来实现文件的导入。

有关 read_csv 函数的使用方法和重要参数的含义如下:

python
# ?pd.read_csv
python
pd.read_csv(
    filepath_or_buffer, #指定导入文件所在的具体路径
    sep=',',        #指定原数据中各变量之间的分隔符,默认是逗号,可自行修改
    header='infer', #默认将数据集首行作为表头(列名),若原数据集无表头,则设置 header=None
    names=None,     #若原数据集中无变量名称,可通过该参数在数据读取时设定
    index_col=None, #指定将某些列作为行索引
    usecols=None,   #指定需要读取的变量名
    converters=None,#通过字典格式,为数据集中的某些变量设置不同的数据类型
    skiprows=None,  #数据读取时,指定需要跳过原数据集的起始行数
    skipfooter=0,   #数据读取时,指定需要跳过原数据集的末尾行数
    nrows=None,     #指定数据读取的行数
    comment=None,   #指定注释符,读取数据时遇到行首指定的注释符则跳过该行
    encoding=None,  #设置编码方式,可以通过设置该参数解决中文乱码问题(通常设为"uft-8"或"gbk")
        )

read_csv函数的所有参数及其含义,可以参考pandas官网:

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

现在尝试读取一个简单的csv文件:

python
pd.read_csv(r"data/taobao_data.csv")
宝贝价格成交量卖家位置
0新款中老年女装春装雪纺打底衫妈妈装夏装中袖宽松上衣中年人t恤99.016647夏奈凤凰旗舰店江苏
1中老年女装清凉两件套妈妈装夏装大码短袖T恤上衣雪纺衫裙裤套装286.014045夏洛特的文艺上海
2母亲节衣服夏季妈妈装夏装套装短袖中年人40-50岁中老年女装T恤298.013458云新旗舰店江苏
3母亲节衣服中老年人春装女40岁50中年妈妈装套装夏装奶奶装两件套279.013340韶妃旗舰店浙江
4中老年女装春夏装裤大码 中年妇女40-50岁妈妈装夏装套装七分裤59.012939千百奈旗舰店江苏
..................
95母亲节中老年女装运动服套装中年妈妈春装外套40岁50衣服2017新款368.04041欧芮嘉旗舰店湖北
96母亲节衣服中年妈妈装夏装短袖套装30中老年女装春装雪纺衫40岁50181.04023浅恋旗舰店浙江
97母亲节妈妈装夏装套装女40-50岁夏季衣服两件套中老年春装连衣裙195.04000若澜锦蒂旗舰店浙江
98母亲节衣服夏季中老年女装夏装短袖套装雪纺衫T恤妈妈装两件套498.03968蕴涵旗舰店江苏
99中老年女装春装t恤纱袖针织衫40-50岁妈妈装七分袖上衣夏装打底衫688.03956潮流前线9170浙江

100 rows × 5 columns


据读取进来之后形成的表格在pandas中称为 DataFrame ( 最常用的 pandas 对象 ),

这是一个带有索引的二维数据结构,每一列可以有自己的名字,并且可以有不同的数据类型,

每一行都有索引,数据读取进来的时候默认会生成从0开始的整数索引,

当然,你也可以自行设置每一行的索引。


现在尝试读取一个稍微复杂一点的数据 staff_info.txt

该数据集并不是一个常规的数据集,其存储的内容包含一些其他杂项:


微信截图_20241207182511

有关该数据集的问题如下:

  • 真正的数据部分仅为 4-10 行,在读取数据时需要忽略其他不相关的内容
  • 数据中没有变量名(列名),在读取数据时需要加上列名
  • 在读取数据时,需要忽略即将离职的两位员工
  • 保证员工编号5位数不变
python
pd.read_csv("data/staff_info.txt"
            
            # 指定原数据分隔符
           ,sep=","
            
            # 声明原数据没有表头
           ,header=None
            
            # 指定列名
           ,names=["编号","姓名","性别","职位"]
            
            # 跳过前两行
           ,skiprows=2
            
            # 跳过最后两行
           ,skipfooter=2
            
            
            # 指定注释符为 “#”  遇到行首为注释符则跳过
           ,comment="#"
            
            # 指定 “编号”这列为 str 数据类型,则不会去除前置0
           ,converters={"编号":str}
            
            """
            不设置engine的话会有warning
            ParserWarning: Falling back to the 'python' engine 
            because the 'c' engine does not support skipfooter;
            """
           ,engine='python'
            
            # 设置编码方式为gbk
            ,encoding='gbk'
           )
编号姓名性别职位
000446张敏前端工程师
100483李琴Java开发工程师
200552赵东来数据分析师
300589丁顺昌数据分析师


  • Excel 文件的读取

读取后缀名为 xls/xlsx 后缀的Excel电子表格数据,

可以使用 read_excel 函数,该函数的用法及重要参数含义如下:

PYTHON
pd.read_excel(
    io,             #指定电子表格的具体路径
    sheet_name=0,   #指定需要读取excel表格中的第几个sheet,也可以直接写sheet名称
    header=0,       #默认将首行作为表头
    names=None,     #若原数据集中无变量名称,可通过该参数在数据读取时设定
    index_col=None, #指定将某些列作为行索引
    usecols=None,   #指定需要读取的变量名
    converters=None,#通过字典格式,为数据集中的某些变量设置不同的数据类型
    skiprows=None,  #数据读取时,指定需要跳过原数据集的起始行数
    skipfooter=0,   #数据读取时,指定需要跳过原数据集的末尾行数
    nrows=None,     #指定数据读取的行数
    comment=None    #指定注释符,读取数据时遇到行首指定的注释符则跳过该行
    )

尝试读取一个 excel 文件 test.xlsx

python
pd.read_excel("data/test.xlsx",sheet_name="nam")
RankCityStatePopulationDate of census/estimate
01London[2]United Kingdom86152462014-06-01
12BerlinGermany34379162014-05-31
23MadridSpain31652352014-01-01
34RomeItaly28720862014-09-30
45ParisFrance22733052013-01-01
..................
100101BonnGermany3098692012-12-31
101102Malm枚Sweden3091052013-03-31
102103NottinghamUnited Kingdom3087352012-06-30
103104KatowicePoland3082692012-06-30
104105KaunasLithuania3068882013-01-01

105 rows × 5 columns



二、数据探索


从外部环境将数据集导入到 Python 之后,第一件要做的事就是了解数据,

例如:数据的规模、各变量的数据类型、简单的描述统计、数据中是否存在 缺失值 / 重复值等。


现有某公司用户的个人信息和交易数据,该数据集涉及的变量为用户id、性别、年龄、

受教育程度、交易金额和交易日期。从表面上看,并未看出数据背后可能存在的问题,

接下来尝试将该数据集导入 Python,仔细观察数据集中存在的问题。

python
# 导入数据集
df = pd.read_excel("data/user_orders.xlsx")
python
# 查看导入数据的前5行
df.head(5)
idnamegenderageeducustom_amtorder_date
0890李小胆李lfemale43.0NaN¥2177.942018年12月25日
12391881xtmale52.0NaN¥2442.182017年5月24日
22785haoahmale39.0NaN¥849.792018年5月15日
31361snaenfemale26.0NaN¥2482.222018年5月16日
4888sue女少female61.0本科¥2027.92018年1月21日
python
# 查看导入数据的后7行
df.tail(3)
idnamegenderageeducustom_amtorder_date
30011129小清新桉蓝female61.0NaN¥139.682018年11月7日
3002674xyyx毓female34.0本科¥670.892018年6月8日
3003229大侦探野荒male64.0NaN¥118.372018年7月13日
python
# 查看数据的规模
df.shape

# (3004, 7)
python
# 查看数据行索引
df.index

# RangeIndex(start=0, stop=3004, step=1)
python
# 查看数据列名
df.columns

"""
Index(['id', 'name', 'gender', 'age', 'edu', 'custom_amt', 'order_date'], dtype='object')
"""
python
# 查看整体信息
df.info()

"""
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3004 entries, 0 to 3003
Data columns (total 7 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   id          3004 non-null   int64  
 1   name        3004 non-null   object 
 2   gender      2868 non-null   object 
 3   age         2904 non-null   float64
 4   edu         1073 non-null   object 
 5   custom_amt  3004 non-null   object 
 6   order_date  3004 non-null   object 
dtypes: float64(1), int64(1), object(5)
memory usage: 164.4+ KB
"""
python
# 进行简单描述统计
df.describe()   #默认统计数值类型
idage
count3004.0000002904.000000
mean1499.90545941.605028
std865.90655514.158348
min1.00000019.000000
25%750.75000030.000000
50%1499.50000040.000000
75%2249.25000055.000000
max3000.000000230.000000
python
# 查看数据集是否存在缺失值
df.isnull().sum()

"""
id               0
name             0
gender         136
age            100
edu           1931
custom_amt       0
order_date       0
dtype: int64
"""

# ps: is_null() 是缺失值则为True,True计数为1,那么sum()就可以得到缺失值个数
python
# 查看数据集是否存在重复值
df.duplicated().sum()

# 4


三、数据选取


探索完数据集之后,我们通常会针对一些特定的数据进行分析或挖掘,

比如针对女性群体研究购物情况;对3月份和4月份产生的交易数据进行对比分析;

仅针对某种支付方式的用户做特征分析等等,这时候就需要对导进来的整个数据集进行筛选,

提取出我们需要的特定数据再进行之后的分析。


python
# 提取某列
df["gender"]

"""
0       female
1         male
2         male
3       female
4       female
         ...  
2999    female
3000    female
3001    female
3002    female
3003      male
Name: gender, Length: 3004, dtype: object
"""

【补充】:

DataFrame 数据结构中提取出来的单列即为pandas中另一数据类型 Series

Series 就是一个带有名称和索引的一维数组。如上面提取出来的这个series,

它的名字就是 “gender” ,它的索引就是从0到3003,

这个一维数组中包含数据全部为object类型

(也就是字符串类型,在pandas中除了整型、浮点型和日期型之外的数据类型统称为object类型)

python
# 提取行
df[5:11]   # 左闭右开
idnamegenderageeducustom_amtorder_date
52387824btmale42.0本科¥854.572018年7月6日
6244angilmale64.0NaN¥2661.942018年8月23日
71155280_tfemale32.0NaN¥70.662017年1月6日
82623ugvufmale48.0NaN¥2346.972017年2月11日
91782王歆允歆王NaN60.0本科¥658.32017年11月15日
101714641兔小male37.0NaN¥1751.682018年3月13日

如果要 这样的区域数据的话(也就是同时对行和列进行筛选),

上述方式将不再适用。

那可以使用 loc 或者 iloc 的方法进行数据区域的筛选。



  • 基于标签的索引—— loc方法

.loc 是基于标签的索引(也可以称为显式索引)大家可以将 loc 中的 l 理解成 "label",

也就是说在loc方法中必须使用数据的标签属性(行标签就是行名称,列标签就是变量名),

否则会返回一个异常。

python
# 提取数据的5-10行,并返回姓名、年龄和交易金额三列

df.loc[5:10,["name","age","custom_amt"]]
nameagecustom_amt
5824bt42.0¥854.57
6angil64.0¥2661.94
7280_t32.0¥70.66
8ugvuf48.0¥2346.97
9王歆允歆王60.0¥658.3
10641兔小37.0¥1751.68
python
# 设置某一列作为索引

df1 = df.set_index("name")
df1.head()
idgenderageeducustom_amtorder_date
name
李小胆李l890female43.0NaN¥2177.942018年12月25日
881xt2391male52.0NaN¥2442.182017年5月24日
haoah2785male39.0NaN¥849.792018年5月15日
snaen1361female26.0NaN¥2482.222018年5月16日
sue女少888female61.0本科¥2027.92018年1月21日
python
# 查看索引

df1.index

"""
Index(['李小胆李l', '881xt', 'haoah', 'snaen', 'sue女少', '824bt', 'angil', '280_t',
       'ugvuf', '王歆允歆王',
       ...
       '团90团米', 'xxhyj', '208财招', '是大航oj', '嗒白白嗒蘇', '宝哒哇是我', '和花花豆豆', '小清新桉蓝',
       'xyyx毓', '大侦探野荒'],
      dtype='object', name='name', length=3004)
"""
python
# 提取["922my","126el","615uy"]三位用户的信息,并返回性别、年龄和学历三列

df1.loc[["922my","126el","615uy"],["gender","age","edu"]]
genderageedu
name
922myfemale29.0本科
126elmale24.0本科
615uyfemale35.0NaN
python
# 提取“李小胆李l”这位用户的全部信息

df1.loc["李小胆李l",:]

"""
id                    890
gender             female
age                    43
edu                   NaN
custom_amt       ¥2177.94
order_date    2018年12月25日
Name: 李小胆李l, dtype: object
"""

loc 方法还可以 和 布尔索引 一起连用:

python
df["age"]<20

"""
0       False
1       False
2       False
3       False
4       False
        ...  
2999    False
3000    False
3001    False
3002    False
3003    False
Name: age, Length: 3004, dtype: bool
"""
python
# 提取出年龄小于20的用户信息

df.loc[df["age"]<20,:]

"""
....运行结果太多..不展示了...
反正就是都满足年龄小于20的信息
"""


  • 基于位置的索引 —— iloc方法

iloc 方法只能通过行号或者列号进行数据的筛选,可以将 iloc 中的 "i" 理解成 "int" ,

也就是通过从0开始的位置索引进行筛选。

对于这种方式的索引,第一行或者第一列必须用0表示。

python
# 提取前5行前3列数据

df.iloc[0:5,0:3]
idnamegender
0890李小胆李lfemale
12391881xtmale
22785haoahmale
31361snaenfemale
4888sue女少female
python
# 先查看一下df1的前五行 

df1.head()
idgenderageeducustom_amtorder_date
name
李小胆李l890female43.0NaN¥2177.942018年12月25日
881xt2391male52.0NaN¥2442.182017年5月24日
haoah2785male39.0NaN¥849.792018年5月15日
snaen1361female26.0NaN¥2482.222018年5月16日
sue女少888female61.0本科¥2027.92018年1月21日
python
# 取行索引为 3-5 , 列索引是 1,3,5 ( 跳选 )

df1.iloc[3:6,[1,3,5]]
gendereduorder_date
name
snaenfemaleNaN2018年5月16日
sue女少female本科2018年1月21日
824btmale本科2018年7月6日
python
# 取行索引 4-9 , 所有列

df.iloc[4:10,:]
idnamegenderageeducustom_amtorder_date
4888sue女少female61.0本科¥2027.92018年1月21日
52387824btmale42.0本科¥854.572018年7月6日
6244angilmale64.0NaN¥2661.942018年8月23日
71155280_tfemale32.0NaN¥70.662017年1月6日
82623ugvufmale48.0NaN¥2346.972017年2月11日
91782王歆允歆王NaN60.0本科¥658.32017年11月15日