【python 库】 pandas 教程

Pandas 安装

安装 pandas 需要基础环境是 Python,开始前我们假定你已经安装了 Python 和 Pip。


使用 pip 安装 pandas:

!pip install pandas
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Requirement already satisfied: pandas in d:\anaconda3\lib\site-packages (1.2.4)
Requirement already satisfied: pytz>=2017.3 in d:\anaconda3\lib\site-packages (from pandas) (2021.1)
Requirement already satisfied: numpy>=1.16.5 in d:\anaconda3\lib\site-packages (from pandas) (1.21.2)
Requirement already satisfied: python-dateutil>=2.7.3 in d:\anaconda3\lib\site-packages (from pandas) (2.8.1)
Requirement already satisfied: six>=1.5 in d:\anaconda3\lib\site-packages (from python-dateutil>=2.7.3->pandas) (1.15.0)

1. 实例 - 查看 pandas 版本

import pandas
pandas.__version__  # 查看版本
'1.2.4'

导入 pandas 一般使用别名 pd 来代替:

import pandas as pd

2. 一个简单的 pandas 实例:

import pandas as pd

mydataset = {
  'sites': ["Google", "Runoob", "Wiki"],
  'number': [1, 2, 3]
}

myvar = pd.DataFrame(mydataset)

print(myvar)
    sites  number
0  Google       1
1  Runoob       2
2    Wiki       3

Pandas 数据结构 - Series

Pandas Series 类似表格中的一个列(column),类似于一维数组,可以保存任何数据类型。

Series 由索引(index)和列组成,函数如下:

pandas.Series( data, index, dtype, name, copy)

参数说明:

  • data:一组数据(ndarray 类型)。

  • index:数据索引标签,如果不指定,默认从 0 开始。

  • dtype:数据类型,默认会自己判断。

  • name:设置名称。

  • copy:拷贝数据,默认为 False。

1. 创建一个简单的 Series 实例(通过列表创建):

import pandas as pd

a = [1, 2, 3]

myvar = pd.Series(a)

print(myvar)
0    1
1    2
2    3
dtype: int64

2. 索引说明

如果没有指定索引,索引值就从 0 开始,我们可以根据索引值读取数据:

print(myvar[1])
2

我们可以指定索引值,如下实例:

import pandas as pd

a = ["Google", "Runoob", "Wiki"]

myvar = pd.Series(a, index = ["x", "y", "z"])

print(myvar)
x    Google
y    Runoob
z      Wiki
dtype: object

根据索引值读取数据:

print(myvar["y"])
Runoob

3. 通过字典创建

我们也可以使用 key/value 对象,类似字典来创建 Series (字典的 key 会变成索引值):

import pandas as pd

sites = {1: "Google", 2: "Runoob", 3: "Wiki"}

myvar = pd.Series(sites)

print(myvar)
1    Google
2    Runoob
3      Wiki
dtype: object

如果我们只需要字典中的一部分数据,只需要指定需要数据的索引即可,如下实例:

myvar = pd.Series(sites, index = [1, 2])

print(myvar)
1    Google
2    Runoob
dtype: object

4. 设置 Series 名称参数

myvar = pd.Series(sites, index = [1, 2], name="RUNOOB-Series-TEST" )

print(myvar)
1    Google
2    Runoob
Name: RUNOOB-Series-TEST, dtype: object

Pandas 数据结构 - DataFrame

DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kboqKrjR-1629103208563)(https://www.runoob.com/wp-content/uploads/2021/04/pandas-DataStructure.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mhBGOiSW-1629103208570)(https://www.runoob.com/wp-content/uploads/2021/04/df-dp.png)]

DataFrame 构造方法如下:

pandas.DataFrame( data, index, columns, dtype, copy)

参数说明:

  • data:一组数据(ndarray、series, map, lists, dict 等类型)。

  • index:索引值,或者可以称为行标签。

  • columns:列标签,默认为 RangeIndex (0, 1, 2, …, n) 。

  • dtype:数据类型。

  • copy:拷贝数据,默认为 False。

Pandas DataFrame 是一个二维的数组结构,类似二维数组。

1. 实例 - 使用列表创建

import pandas as pd

data = [['Google',10],['Runoob',12],['Wiki',13]]

df = pd.DataFrame(data,columns=['Site','Age'],dtype=float)

print(df)
     Site   Age
0  Google  10.0
1  Runoob  12.0
2    Wiki  13.0

以下实例使用 ndarrays 创建,ndarray 的长度必须相同, 如果传递了 index,则索引的长度应等于数组的长度。如果没有传递索引,则默认情况下,索引将是range(n),其中n是数组长度。

ndarrays 可以参考:NumPy Ndarray 对象

2. 实例 - 使用 ndarrays 创建

import pandas as pd

data = {'Site':['Google', 'Runoob', 'Wiki'], 'Age':[10, 12, 13]}

df = pd.DataFrame(data)

print (df)
     Site  Age
0  Google   10
1  Runoob   12
2    Wiki   13

还可以使用字典(key/value),其中字典的 key 为列名:

3. 实例 - 使用字典创建

import pandas as pd

data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]

df = pd.DataFrame(data)

print (df)
   a   b     c
0  1   2   NaN
1  5  10  20.0

没有对应的部分数据为 NaN。

4. 数据索引

Pandas 可以使用 loc 属性返回指定行的数据,如果没有设置索引,第一行索引为 0,第二行索引为 1,以此类推:

import pandas as pd

data = {
  "calories": [420, 380, 390],
  "duration": [50, 40, 45]
}

# 数据载入到 DataFrame 对象
df = pd.DataFrame(data)

print(df)
   calories  duration
0       420        50
1       380        40
2       390        45
# 返回第一行
print(df.loc[0])
calories    420
duration     50
Name: 0, dtype: int64
# 返回第二行
print(df.loc[1])
calories    380
duration     40
Name: 1, dtype: int64

注意: 返回结果其实就是一个 Pandas Series 数据。


也可以返回多行数据,使用 [[ ... ]] 格式,... 为各行的索引,以逗号隔开:

# 返回第一行和第二行
print(df.loc[[0, 1]])
   calories  duration
0       420        50
1       380        40

注意: 返回结果其实就是一个 Pandas DataFrame 数据。


5. 指定索引值

我们可以指定索引值,如下实例:

df = pd.DataFrame(data, index = ["day1", "day2", "day3"])

print(df)
      calories  duration
day1       420        50
day2       380        40
day3       390        45

Pandas 可以使用 loc 属性返回指定索引对应到某一行:

# 指定索引
print(df.loc["day2"])
calories    380
duration     40
Name: day2, dtype: int64

Pandas CSV 文件

CSV(Comma-Separated Values,逗号分隔值,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。

CSV 是一种通用的、相对简单的文件格式,被用户、商业和科学广泛应用。

1. 导入CSV文件

import pandas as pd

#从文件导入
df = pd.read_csv('./File/nba.csv')

#从url导入
df = pd.read_csv('https://static.runoob.com/download/nba.csv')

print(df.to_string())

to_string() 用于返回 DataFrame 类型的数据,如果不使用该函数,则输出结果为数据的前面 5 行和末尾 5 行,中间部分以 ... 代替。

print(df)
              Name            Team  Number Position   Age Height  Weight  \
0    Avery Bradley  Boston Celtics     0.0       PG  25.0    6-2   180.0   
1      Jae Crowder  Boston Celtics    99.0       SF  25.0    6-6   235.0   
2     John Holland  Boston Celtics    30.0       SG  27.0    6-5   205.0   
3      R.J. Hunter  Boston Celtics    28.0       SG  22.0    6-5   185.0   
4    Jonas Jerebko  Boston Celtics     8.0       PF  29.0   6-10   231.0   
..             ...             ...     ...      ...   ...    ...     ...   
453   Shelvin Mack       Utah Jazz     8.0       PG  26.0    6-3   203.0   
454      Raul Neto       Utah Jazz    25.0       PG  24.0    6-1   179.0   
455   Tibor Pleiss       Utah Jazz    21.0        C  26.0    7-3   256.0   
456    Jeff Withey       Utah Jazz    24.0        C  26.0    7-0   231.0   
457            NaN             NaN     NaN      NaN   NaN    NaN     NaN   

               College     Salary  
0                Texas  7730337.0  
1            Marquette  6796117.0  
2    Boston University        NaN  
3        Georgia State  1148640.0  
4                  NaN  5000000.0  
..                 ...        ...  
453             Butler  2433333.0  
454                NaN   900000.0  
455                NaN  2900000.0  
456             Kansas   947276.0  
457                NaN        NaN  

[458 rows x 9 columns]

2. 导出为csv文件

我们也可以使用 to_csv() 方法将 DataFrame 存储为 csv 文件:

import pandas as pd
   
# 三个字段 name, site, age
nme = ["Google", "Runoob", "Taobao", "Wiki"]
st = ["www.google.com", "www.runoob.com", "www.taobao.com", "www.wikipedia.org"]
ag = [90, 40, 80, 98]
   
# 字典
dict = {'name': nme, 'site': st, 'age': ag}
     
df = pd.DataFrame(dict)
# 保存 dataframe
df.to_csv('./File/site.csv')

执行成功后,我们打开 site.csv 文件,显示结果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dBb8ukVy-1629103208572)(https://www.runoob.com/wp-content/uploads/2021/05/9758194A-0D8E-4C53-95A0-157C690614E6.jpg)]

3. 数据处理 - head()

head( n ) 方法用于读取前面的 n 行,如果不填参数 n ,默认返回 5 行。

import pandas as pd

df = pd.read_csv('./File/nba.csv')

print(df.head())
            Name            Team  Number Position   Age Height  Weight  \
0  Avery Bradley  Boston Celtics     0.0       PG  25.0    6-2   180.0   
1    Jae Crowder  Boston Celtics    99.0       SF  25.0    6-6   235.0   
2   John Holland  Boston Celtics    30.0       SG  27.0    6-5   205.0   
3    R.J. Hunter  Boston Celtics    28.0       SG  22.0    6-5   185.0   
4  Jonas Jerebko  Boston Celtics     8.0       PF  29.0   6-10   231.0   

             College     Salary  
0              Texas  7730337.0  
1          Marquette  6796117.0  
2  Boston University        NaN  
3      Georgia State  1148640.0  
4                NaN  5000000.0  

4. 数据处理 - tail()

tail( n ) 方法用于读取尾部的 n 行,如果不填参数 n ,默认返回 5 行,空行各个字段的值返回 NaN。

print(df.tail())
             Name       Team  Number Position   Age Height  Weight College  \
453  Shelvin Mack  Utah Jazz     8.0       PG  26.0    6-3   203.0  Butler   
454     Raul Neto  Utah Jazz    25.0       PG  24.0    6-1   179.0     NaN   
455  Tibor Pleiss  Utah Jazz    21.0        C  26.0    7-3   256.0     NaN   
456   Jeff Withey  Utah Jazz    24.0        C  26.0    7-0   231.0  Kansas   
457           NaN        NaN     NaN      NaN   NaN    NaN     NaN     NaN   

        Salary  
453  2433333.0  
454   900000.0  
455  2900000.0  
456   947276.0  
457        NaN  

5. 数据处理 - info()

info() 方法返回表格的一些基本信息:

print(df.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 458 entries, 0 to 457
Data columns (total 9 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   Name      457 non-null    object 
 1   Team      457 non-null    object 
 2   Number    457 non-null    float64
 3   Position  457 non-null    object 
 4   Age       457 non-null    float64
 5   Height    457 non-null    object 
 6   Weight    457 non-null    float64
 7   College   373 non-null    object 
 8   Salary    446 non-null    float64
dtypes: float64(4), object(5)
memory usage: 32.3+ KB
None

Pandas JSON

JSON(JavaScript Object Notation,JavaScript 对象表示法),是存储和交换文本信息的语法,类似 XML。

JSON 比 XML 更小、更快,更易解析,更多 JSON 内容可以参考 JSON 教程

1. 将 JSON 字符串转化为 DataFrame

import pandas as pd

data =[
    {
      "id": "A001",
      "name": "菜鸟教程",
      "url": "www.runoob.com",
      "likes": 61
    },
    {
      "id": "A002",
      "name": "Google",
      "url": "www.google.com",
      "likes": 124
    },
    {
      "id": "A003",
      "name": "淘宝",
      "url": "www.taobao.com",
      "likes": 45
    }
]
df = pd.DataFrame(data)

print(df)
     id    name             url  likes
0  A001    菜鸟教程  www.runoob.com     61
1  A002  Google  www.google.com    124
2  A003      淘宝  www.taobao.com     45

2. 导入JSON

其中 to_string() 用于返回 DataFrame 类型的数据。

import pandas as pd

#从文件导入
df = pd.read_json('./File/sites.json')

#从url导入
df = pd.read_json('https://static.runoob.com/download/sites.json')
   
print(df.to_string())
     id    name             url  likes
0  A001    菜鸟教程  www.runoob.com     61
1  A002  Google  www.google.com    124
2  A003      淘宝  www.taobao.com     45

3. 读取内嵌的 JSON 数据

假设有一组内嵌的 JSON 数据文件 nested_list.json

{
    "school_name": "ABC primary school",
    "class": "Year 1",
    "students": [
    {
        "id": "A001",
        "name": "Tom",
        "math": 60,
        "physics": 66,
        "chemistry": 61
    },
    {
        "id": "A002",
        "name": "James",
        "math": 89,
        "physics": 76,
        "chemistry": 51
    },
    {
        "id": "A003",
        "name": "Jenny",
        "math": 79,
        "physics": 90,
        "chemistry": 78
    }]
}

使用以下代码格式化完整内容:

import pandas as pd

df = pd.read_json('./File/nested_list.json')

print(df)
          school_name   class  \
0  ABC primary school  Year 1   
1  ABC primary school  Year 1   
2  ABC primary school  Year 1   

                                            students  
0  {'id': 'A001', 'name': 'Tom', 'math': 60, 'phy...  
1  {'id': 'A002', 'name': 'James', 'math': 89, 'p...  
2  {'id': 'A003', 'name': 'Jenny', 'math': 79, 'p...  

可以看出输出结果并不理想,这时我们就需要使用到 json_normalize() 方法将内嵌的数据完整的解析出来:

import pandas as pd
import json
# 使用 Python JSON 模块载入数据
with open('./File/nested_list.json','r') as f:
    data = json.loads(f.read())
# 展平数据
df_nested_list = pd.json_normalize(data, record_path =['students'])
print(df_nested_list)
     id   name  math  physics  chemistry
0  A001    Tom    60       66         61
1  A002  James    89       76         51
2  A003  Jenny    79       90         78
# 展平数据
df_nested_list = pd.json_normalize(
    data,
    record_path =['students'],
    meta=['school_name', 'class']
)
print(df_nested_list)
     id   name  math  physics  chemistry         school_name   class
0  A001    Tom    60       66         61  ABC primary school  Year 1
1  A002  James    89       76         51  ABC primary school  Year 1
2  A003  Jenny    79       90         78  ABC primary school  Year 1

json_normalize() 使用了参数 record_path 并设置为 ['students'] 用于展开内嵌的 JSON 数据 students

显示结果还没有包含 school_nameclass 元素,如果需要展示出来可以使用 meta 参数来显示这些元数据


接下来,让我们尝试读取更复杂的 JSON 数据,该数据嵌套了列表和字典,数据文件 nested_mix.json 如下:

{
    "school_name": "local primary school",
    "class": "Year 1",
    "info": {
      "president": "John Kasich",
      "address": "ABC road, London, UK",
      "contacts": {
        "email": "admin@e.com",
        "tel": "123456789"
      }
    },
    "students": [
    {
        "id": "A001",
        "name": "Tom",
        "math": 60,
        "physics": 66,
        "chemistry": 61
    },
    {
        "id": "A002",
        "name": "James",
        "math": 89,
        "physics": 76,
        "chemistry": 51
    },
    {
        "id": "A003",
        "name": "Jenny",
        "math": 79,
        "physics": 90,
        "chemistry": 78
    }]
}
import pandas as pd
import json

# 使用 Python JSON 模块载入数据
with open('./File/nested_mix.json','r') as f:
    data = json.loads(f.read())
    
df = pd.json_normalize(
    data,
    record_path =['students'],
    meta=[
        'class',
        ['info', 'president'],
        ['info', 'contacts', 'tel']
    ]
)

print(df)
     id   name  math  physics  chemistry   class info.president  \
0  A001    Tom    60       66         61  Year 1    John Kasich   
1  A002  James    89       76         51  Year 1    John Kasich   
2  A003  Jenny    79       90         78  Year 1    John Kasich   

  info.contacts.tel  
0         123456789  
1         123456789  
2         123456789  

4. 读取内嵌数据中的一组数据

以下是实例文件 nested_deep.json,我们只读取内嵌中的 math 字段:

{
    "school_name": "local primary school",
    "class": "Year 1",
    "students": [
    {
        "id": "A001",
        "name": "Tom",
        "grade": {
            "math": 60,
            "physics": 66,
            "chemistry": 61
        }
 
    },
    {
        "id": "A002",
        "name": "James",
        "grade": {
            "math": 89,
            "physics": 76,
            "chemistry": 51
        }
       
    },
    {
        "id": "A003",
        "name": "Jenny",
        "grade": {
            "math": 79,
            "physics": 90,
            "chemistry": 78
        }
    }]
}

这里我们需要使用到 glom 模块来处理数据套嵌,glom 模块允许我们使用 . 来访问内嵌对象的属性。

第一次使用我们需要安装 glom

!pip3 install glom
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting glom
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/5a/e2/977d77f6e0c34902f05a0754beb5950ea70c3c3c935d571fccac9540b57a/glom-20.11.0-py2.py3-none-any.whl (97 kB)
Collecting boltons>=19.3.0
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/f7/a7/1a31561d10a089fcb46fe286766dd4e053a12f6e23b4fd1c26478aff2475/boltons-21.0.0-py2.py3-none-any.whl (193 kB)
Collecting face>=20.1.0
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/ae/ab/2b18c4815f3db1e04bce325271fefda55d0893738ea84e3a655218944b03/face-20.1.1.tar.gz (46 kB)
Requirement already satisfied: attrs in d:\anaconda3\lib\site-packages (from glom) (20.3.0)
Building wheels for collected packages: face
  Building wheel for face (setup.py): started
  Building wheel for face (setup.py): finished with status 'done'
  Created wheel for face: filename=face-20.1.1-py3-none-any.whl size=51078 sha256=1547f9fd13aea806ec4b29d006a5527a22ef2f5814da457d8d28be3b6c1441e0
  Stored in directory: c:\users\dell\appdata\local\pip\cache\wheels\38\1e\e8\a4032cdb26900d12a09e565200404c1ceb4756fab5ae346f52
Successfully built face
Installing collected packages: boltons, face, glom
Successfully installed boltons-21.0.0 face-20.1.1 glom-20.11.0
import pandas as pd
from glom import glom
df = pd.read_json('./File/nested_deep.json')
print(df)
            school_name   class  \
0  local primary school  Year 1   
1  local primary school  Year 1   
2  local primary school  Year 1   

                                            students  
0  {'id': 'A001', 'name': 'Tom', 'grade': {'math'...  
1  {'id': 'A002', 'name': 'James', 'grade': {'mat...  
2  {'id': 'A003', 'name': 'Jenny', 'grade': {'mat...  

dataframe.apply(function, axis) 对一行或一列做出一些操作

  • axis = 1 遍历行(默认)
  • axis = 0 遍历列
# 第0行 
print(df['students'][0])

df['students'][0]
{'id': 'A001', 'name': 'Tom', 'grade': {'math': 60, 'physics': 66, 'chemistry': 61}}





{'id': 'A001',
 'name': 'Tom',
 'grade': {'math': 60, 'physics': 66, 'chemistry': 61}}
# 遍历每一行并打印
df['students'].apply(print) 

#每一行都打印了出来,但每次打印返回值均为0,因此三行均为None
{'id': 'A001', 'name': 'Tom', 'grade': {'math': 60, 'physics': 66, 'chemistry': 61}}
{'id': 'A002', 'name': 'James', 'grade': {'math': 89, 'physics': 76, 'chemistry': 51}}
{'id': 'A003', 'name': 'Jenny', 'grade': {'math': 79, 'physics': 90, 'chemistry': 78}}





0    None
1    None
2    None
Name: students, dtype: object
# 读取第0行 math 字段
glom(df['students'][0], 'grade.math')
60
# 读取所有三行 math 字段 并组合为新的 Series
data = df['students'].apply(lambda row: glom(row, 'grade.math'))
print(data)
0    60
1    89
2    79
Name: students, dtype: int64

Pandas 数据清洗

数据清洗是对一些没有用的数据进行处理的过程。

很多数据集存在数据缺失、数据格式错误、错误数据或重复数据的情况,如果要对使数据分析更加准确,就需要对这些没有用的数据进行处理。

在这个教程中,我们将利用 Pandas包来进行数据清洗。

本文使用到的测试数据 property-data.csv 如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJOBvbmb-1629103208575)(https://www.runoob.com/wp-content/uploads/2021/06/6A6DE9DA-E0EE-4001-8C21-1D6A8EBF70FF.jpeg)]

上表包含来四种空数据:

  • n/a
  • NA
  • na

导入数据:

import pandas as pd

df = pd.read_csv('./File/property-data.csv')

print(df)
           PID  ST_NUM     ST_NAME OWN_OCCUPIED NUM_BEDROOMS NUM_BATH SQ_FT
0  100001000.0   104.0      PUTNAM            Y            3        1  1000
1  100002000.0   197.0   LEXINGTON            N            3      1.5    --
2  100003000.0     NaN   LEXINGTON            N          NaN        1   850
3  100004000.0   201.0    BERKELEY           12            1      NaN   700
4          NaN   203.0    BERKELEY            Y            3        2  1600
5  100006000.0   207.0    BERKELEY            Y          NaN        1   800
6  100007000.0     NaN  WASHINGTON          NaN            2   HURLEY   950
7  100008000.0   213.0     TREMONT            Y            1        1   NaN
8  100009000.0   215.0     TREMONT            Y           na        2  1800

1. Pandas 清洗空值

(1) 判断判断各个单元格是否为空 : isnull()

print (df.isnull())
     PID  ST_NUM  ST_NAME  OWN_OCCUPIED  NUM_BEDROOMS  NUM_BATH  SQ_FT
0  False   False    False         False         False     False  False
1  False   False    False         False         False     False  False
2  False    True    False         False          True     False  False
3  False   False    False         False         False      True  False
4   True   False    False         False         False     False  False
5  False   False    False         False          True     False  False
6  False    True    False          True         False     False  False
7  False   False    False         False         False     False   True
8  False   False    False         False         False     False  False

以上例子中我们看到 Pandas 把 n/a 和 NA 当作空数据,na 不是空数据,不符合我们要求,我们可以指定空数据类型

missing_values = ["n/a", "na", "--"]

df = pd.read_csv('./File/property-data.csv', na_values = missing_values)

print(df)
           PID  ST_NUM     ST_NAME OWN_OCCUPIED  NUM_BEDROOMS NUM_BATH   SQ_FT
0  100001000.0   104.0      PUTNAM            Y           3.0        1  1000.0
1  100002000.0   197.0   LEXINGTON            N           3.0      1.5     NaN
2  100003000.0     NaN   LEXINGTON            N           NaN        1   850.0
3  100004000.0   201.0    BERKELEY           12           1.0      NaN   700.0
4          NaN   203.0    BERKELEY            Y           3.0        2  1600.0
5  100006000.0   207.0    BERKELEY            Y           NaN        1   800.0
6  100007000.0     NaN  WASHINGTON          NaN           2.0   HURLEY   950.0
7  100008000.0   213.0     TREMONT            Y           1.0        1     NaN
8  100009000.0   215.0     TREMONT            Y           NaN        2  1800.0
print (df.isnull())
     PID  ST_NUM  ST_NAME  OWN_OCCUPIED  NUM_BEDROOMS  NUM_BATH  SQ_FT
0  False   False    False         False         False     False  False
1  False   False    False         False         False     False   True
2  False    True    False         False          True     False  False
3  False   False    False         False         False      True  False
4   True   False    False         False         False     False  False
5  False   False    False         False          True     False  False
6  False    True    False          True         False     False  False
7  False   False    False         False         False     False   True
8  False   False    False         False          True     False  False

(2) 删除包含空数据的行或列:dropna()

DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

参数说明:

  • axis:默认为 0,表示逢空值剔除整行,如果设置参数 axis=1 表示逢空值去掉整列。
  • how:默认为 ‘any’ 如果一行(或一列)里任何一个数据有出现 NA 就去掉整行,如果设置 how=‘all’ 一行(或列)都是 NA 才去掉这整行。
  • thresh:设置需要多少非空值的数据才可以保留下来的。
  • subset:设置想要检查的列。如果是多个列,可以使用列名的 list 作为参数。
  • inplace:如果设置 True,将计算得到的值直接覆盖之前的值并返回 None,修改的是源数据。

注意: 默认情况下,dropna() 方法返回一个新的 DataFrame,不会修改源数据。

如果你要修改源数据 DataFrame, 可以使用 inplace = True 参数:

# 删除包含空数据的行

new_df = df.dropna()

print(new_df.to_string())
           PID  ST_NUM ST_NAME OWN_OCCUPIED  NUM_BEDROOMS NUM_BATH   SQ_FT
0  100001000.0   104.0  PUTNAM            Y           3.0        1  1000.0
# 移除指定列有空值的行

new_df = df.dropna(subset=['ST_NUM'])

print(new_df.to_string())
           PID  ST_NUM    ST_NAME OWN_OCCUPIED  NUM_BEDROOMS NUM_BATH   SQ_FT
0  100001000.0   104.0     PUTNAM            Y           3.0        1  1000.0
1  100002000.0   197.0  LEXINGTON            N           3.0      1.5     NaN
3  100004000.0   201.0   BERKELEY           12           1.0      NaN   700.0
4          NaN   203.0   BERKELEY            Y           3.0        2  1600.0
5  100006000.0   207.0   BERKELEY            Y           NaN        1   800.0
7  100008000.0   213.0    TREMONT            Y           1.0        1     NaN
8  100009000.0   215.0    TREMONT            Y           NaN        2  1800.0

(3) 替换空字段:fillna()

# 使用 12345 替换空字段:

new_df = df.fillna(12345)

print(new_df.to_string())
           PID   ST_NUM     ST_NAME OWN_OCCUPIED  NUM_BEDROOMS NUM_BATH    SQ_FT
0  100001000.0    104.0      PUTNAM            Y           3.0        1   1000.0
1  100002000.0    197.0   LEXINGTON            N           3.0      1.5  12345.0
2  100003000.0  12345.0   LEXINGTON            N       12345.0        1    850.0
3  100004000.0    201.0    BERKELEY           12           1.0    12345    700.0
4      12345.0    203.0    BERKELEY            Y           3.0        2   1600.0
5  100006000.0    207.0    BERKELEY            Y       12345.0        1    800.0
6  100007000.0  12345.0  WASHINGTON        12345           2.0   HURLEY    950.0
7  100008000.0    213.0     TREMONT            Y           1.0        1  12345.0
8  100009000.0    215.0     TREMONT            Y       12345.0        2   1800.0
# 指定某一个列来替换数据

df['PID'].fillna(12345, inplace = True)

print(df.to_string())
           PID  ST_NUM     ST_NAME OWN_OCCUPIED  NUM_BEDROOMS NUM_BATH   SQ_FT
0  100001000.0   104.0      PUTNAM            Y           3.0        1  1000.0
1  100002000.0   197.0   LEXINGTON            N           3.0      1.5     NaN
2  100003000.0     NaN   LEXINGTON            N           NaN        1   850.0
3  100004000.0   201.0    BERKELEY           12           1.0      NaN   700.0
4      12345.0   203.0    BERKELEY            Y           3.0        2  1600.0
5  100006000.0   207.0    BERKELEY            Y           NaN        1   800.0
6  100007000.0     NaN  WASHINGTON          NaN           2.0   HURLEY   950.0
7  100008000.0   213.0     TREMONT            Y           1.0        1     NaN
8  100009000.0   215.0     TREMONT            Y           NaN        2  1800.0

扩展:替换空单元格的常用方法是计算列的均值、中位数值或众数

Pandas使用 mean()median()mode() 方法计算列的均值(所有值加起来的平均值)、中位数值(排序后排在中间的数)和众数(出现频率最高的数)。

# 使用 mean() 方法计算列的均值并替换空单元格

import pandas as pd

df = pd.read_csv('./File/property-data.csv')

x = df["ST_NUM"].mean()

df["ST_NUM"].fillna(x, inplace = True)

print(df.to_string())
           PID      ST_NUM     ST_NAME OWN_OCCUPIED NUM_BEDROOMS NUM_BATH SQ_FT
0  100001000.0  104.000000      PUTNAM            Y            3        1  1000
1  100002000.0  197.000000   LEXINGTON            N            3      1.5    --
2  100003000.0  191.428571   LEXINGTON            N          NaN        1   850
3  100004000.0  201.000000    BERKELEY           12            1      NaN   700
4          NaN  203.000000    BERKELEY            Y            3        2  1600
5  100006000.0  207.000000    BERKELEY            Y          NaN        1   800
6  100007000.0  191.428571  WASHINGTON          NaN            2   HURLEY   950
7  100008000.0  213.000000     TREMONT            Y            1        1   NaN
8  100009000.0  215.000000     TREMONT            Y           na        2  1800

2. Pandas 清洗格式错误数据

数据格式错误的单元格会使数据分析变得困难,甚至不可能。

我们可以通过包含空单元格的行,或者将列中的所有单元格转换为相同格式的数据。

以下实例会 格式化日期

import pandas as pd

# 第三个日期格式错误
data = {
  "Date": ['2020/12/01', '2020/12/02' , '20201226'],
  "duration": [50, 40, 45]
}

df = pd.DataFrame(data, index = ["day1", "day2", "day3"])

df['Date'] = pd.to_datetime(df['Date'])

print(df.to_string())
           Date  duration
day1 2020-12-01        50
day2 2020-12-02        40
day3 2020-12-26        45

3. Pandas 清洗错误数据

数据错误也是很常见的情况,我们可以对错误的数据进行替换或移除。

导入有关年龄的数据:

import pandas as pd

person = {
  "name": ['Google', 'Runoob' , 'Taobao'],
  "age": [50, 40, 12345]    # 12345 年龄数据是错误的
}
# 替换错误年龄的数据

df = pd.DataFrame(person)

df.loc[2, 'age'] = 30 # 修改数据

print(df.to_string())
     name  age
0  Google   50
1  Runoob   40
2  Taobao   30
# 也可以设置条件语句
# 将 age 大于 120 的设置为 120

df = pd.DataFrame(person)

for x in df.index:
  if df.loc[x, "age"] > 120:
    df.loc[x, "age"] = 120

print(df.to_string())
     name  age
0  Google   50
1  Runoob   40
2  Taobao  120
# 将错误数据的行删除

df = pd.DataFrame(person)

for x in df.index:
  if df.loc[x, "age"] > 120:
    df.drop(x, inplace = True)

print(df.to_string())
     name  age
0  Google   50
1  Runoob   40

4. Pandas 清洗重复数据

如果我们要清洗重复数据,可以使用 duplicated()drop_duplicates() 方法。

如果对应的数据是重复的,duplicated() 会返回 True,否则返回 False

import pandas as pd

person = {
  "name": ['Google', 'Runoob', 'Runoob', 'Taobao'],
  "age": [50, 40, 40, 23]  
}
df = pd.DataFrame(person)

print(df.duplicated())
0    False
1    False
2     True
3    False
dtype: bool

删除重复数据,可以直接使用 drop_duplicates() 方法。

df = pd.DataFrame(person)

df.drop_duplicates(inplace = True)
print(df)
     name  age
0  Google   50
1  Runoob   40
3  Taobao   23

版权声明:本文为weixin_43964993原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。