pandas数据处理基础

Pandas 数据处理基础

1.Pandas介绍:

** Pandas 是非常著名的开源数据处理库,我们可以通过它完成对数据集进行快速读取、转换、过滤、分析等一系列操作。除此之外,Pandas 拥有强大的缺失数据处理与数据透视功能,可谓是数据预处理中的必备利器。**

** Pandas 是非常著名的开源数据处理库,其基于 NumPy 开发,该工具是 Scipy 生态中为了解决数据分析任务而设计。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的函数和方法。**

** 特有的数据结构是 Pandas 的优势和核心。简单来讲,我们可以将任意格式的数据转换为 Pandas 的数据类型,并使用 Pandas 提供的一系列方法进行转换、操作,最终得到我们期望的结果。**

2.数据类型:

Pandas 的数据类型主要有以下几种,它们分别是:Series(一维数组),DataFrame(二维数组),Panel(三维数组),Panel4D(四维数组),PanelND(更多维数组)。其中 Series 和 DataFrame 应用的最为广泛,几乎占据了使用频率 90% 以上。

(1)Series:

Series 是 Pandas 中最基本的一维数组形式。其可以储存整数、浮点数、字符串等类型的数据。** ​ 基本用法结构:

                   
pandas.Series(data=None, index=None)

data 可以是字典,或者NumPy 里的 ndarray 对象等。index 是数据索引,索引是 Pandas 数据结构中的一大特性,它主要的功能是帮助我们更快速地定位数据。** 具体实现:

%matplotlib inline
    import pandas as pd
    s = pd.Series({'a': 10, 'b': 20, 'c': 30})
    s   ==>  a    10
                  b    20
                  c    30
                 dtype: int64

 

通过 type 来确认 s 的类型:

type(s) ==>  pandas.core.series.Series

由于 Pandas 基于 NumPy 开发。那么 NumPy 的数据类型 ndarray 多维数组自然就可以转换为 Pandas 中的数据。而 Series 则可以基于 NumPy 中的一维数据转换。

import numpy as np
​
s = pd.Series(np.random.randn(5))
s ==>
0   -0.769720
1    0.047676
2    0.516502
3    1.570160
4   -0.200160
dtype: float64

如上所示,我们给出了 NumPy 生成的一维随机数组,最终得到的 Series 索引默认从 0 开始,而数值类型为 float64。

(2)DataFrame:

DataFrame 是 Pandas 中最为常见、最重要且使用频率最高的数据结构。DataFrame 和平常的电子表格或 SQL 表结构相似。你可以把 DataFrame 看成是 Series 的扩展类型,它仿佛是由多个 Series 拼合而成。它和 Series 的直观区别在于,数据不但具有行索引,且具有列索引。 ​ 基本用法结构:            

pandas.DataFrame(data=None, index=None, columns=None)

区别于 Series,其增加了 columns 列索引

DataFrame 可以由以下多个类型的数据构建: 1) 一维数组、列表、字典或者 Series 字典。 2) 二维或者结构化的 numpy.ndarray。 3) 一个 Series 或者另一个 DataFrame。

具体例子:

df = pd.DataFrame({'one': pd.Series([1, 2, 3]),
                  'two': pd.Series([4, 5, 6])})
df ==》
  onetwo
0   1 4
12 5
23 6

当不指定索引时,DataFrame 的索引同样是从 0 开始。我们也可以直接通过一个列表构成的字典来生成 DataFrame。

df = pd.DataFrame({'one': [1, 2, 3],
                  'two': [4, 5, 6]})
df ==>
             one          two
0              1              4
1              2              5
2              3              6
#或者反过来,由带字典的列表生成 DataFrame。
df = pd.DataFrame([{'one': 1, 'two': 4},
                  {'one': 2, 'two': 5},
                  {'one': 3, 'two': 6}])
df ==>
             one          two
0              1              4
1              2              5
2              3              6

 

NumPy 的多维数组非常常用,同样可以基于二维数值来构建一个 DataFrame。

pd.DataFrame(np.random.randint(5, size=(2, 4)))  
==>
              0               1              2             3
0              4               0              4             3
1              0               4              0             1

至此,你应该已经清楚了 Pandas 常用的 Series 和 DataFrame 数据类型。Series 实际上可以被初略看出是只有 1 列数据的 DataFrame。当然,这个说法不严谨,二者的核心区别仍然是 Series 没有列索引。你可以观察如下所示由 NumPy 一维随机数组生成的 Series 和 DataFrame。

pd.Series(np.random.randint(5, size=(5,))) 
==> 
0    4
1    2
2    1
3    0
4    1
dtype: int64

pd.DataFrame(np.random.randint(5, size=(5,)))  
==> 	
               0
0              1
1              0
2              0
3              1
4              3

关于 Pandas 中的 Panel 等数据类型我们就不再介绍。首先是这些数据类型用的很少,其次就算你用到了,也可以通过从 DataFrame 等学到的技巧进行迁移应用,万变不离其宗。

3.数据读取

我们想要使用 Pandas 来分析数据,那么首先需要读取数据。大多数情况下,数据都来源于外部的数据文件或者数据库。Pandas 提供了一系列的方法来读取外部数据,非常全面。

读取数据 CSV 文件的方法是 pandas.read_csv(),你可以直接传入一个相对路径,或者是网络 URL。

df = pd.read_csv("https://labfile.oss.aliyuncs.com/courses/906/los_census.csv")
df  ==> 
     Zip Code  Total Population  Median Age  Total Males  Total Females  
0       91371                 1        73.5            0              1   
1       90001             57110        26.6        28468          28642   
2       90002             51223        25.5        24876          26347   
3       90003             66266        26.3        32631          33635   
4       90004             62180        34.8        31302          30878   
..        ...               ...         ...          ...            ...   
314     93552             38158        28.4        18711          19447   
315     93553              2138        43.3         1121           1017   
316     93560             18910        32.4         9491           9419   
317     93563               388        44.5          263            125   
318     93591              7285        30.9         3653           3632   

     Total Households  Average Household Size  
0                   1                    1.00  
1               12971                    4.40  
2               11731                    4.36  
3               15642                    4.22  
4               22547                    2.73  
..                ...                     ...  
314              9690                    3.93  
315               816                    2.62  
316              6469                    2.92  
317               103                    2.53  
318              1982                    3.67  

[319 rows x 7 columns]

由于 CSV 存储时是一个二维的表格,那么 Pandas 会自动将其读取为 DataFrame 类型。

现在你应该就明白了,DataFrame 是 Pandas 构成的核心。一切的数据,无论是外部读取还是自行生成,我们都需要先将其转换为 Pandas 的 DataFrame 或者 Series 数据类型。实际上,大多数情况下,这一切都是设计好的,无需执行额外的转换工作。

pd.read_ 前缀开始的方法还可以读取各式各样的数据文件,且支持连接数据库。这里,我们不再依次赘述,你可以阅读 官方文档相应章节 熟悉这些方法以及搞清楚这些方法包含的参数。

你可能又一个疑问:为什么要将数据转换为 Series 或者 DataFrame 结构? 实际上,我现在就可以先回答这个问题。因为 Pandas 针对数据操作的全部方法都是基于 Pandas 支持的数据结构设计的。也就是说,只有 Series 或者 DataFrame 才能使用 Pandas 提供的方法和函数进行处理。所以,学习真正数据处理方法之前,我们需要将数据转换生成为 Series 或 DataFrame 类型。

4.基本操作

一个 DataFrame 结构大致由 3 部分组成,它们分别是列名称、索引和数据。

上面,我们已经读取了一个外部数据,这是洛杉矶的人口普查数据。有些时候,我们读取的文件很大。如果全部输出预览这些文件,既不美观,又很耗时。还好,Pandas 提供了 head() 和 tail() 方法,它可以帮助我们只预览一小块数据。

df.head()  # 默认显示前 5 条 

输出图片:

df.tail(7)  # 指定显示后 7 条
  ==> 
       Zip Code  Total Population  Median Age  Total Males  Total Females  \
312     93550             74929        27.5        36414          38515   
313     93551             50798        37.0        25056          25742   
314     93552             38158        28.4        18711          19447   
315     93553              2138        43.3         1121           1017   
316     93560             18910        32.4         9491           9419   
317     93563               388        44.5          263            125   
318     93591              7285        30.9         3653           3632   

     Total Households  Average Household Size  
312             20864                    3.58  
313             15963                    3.18  
314              9690                    3.93  
315               816                    2.62  
316              6469                    2.92  
317               103                    2.53  
318              1982                    3.67 

Pandas 还提供了统计和描述性方法,方便你从宏观的角度去了解数据集。describe() 相当于对数据集进行概览,会输出该数据集每一列数据的计数、最大值、最小值等。

df.describe()
==>
           Zip Code  Total Population  Median Age   Total Males  \
count    319.000000        319.000000  319.000000    319.000000   
mean   91000.673981      33241.341693   36.527586  16391.564263   
std      908.360203      21644.417455    8.692999  10747.495566   
min    90001.000000          0.000000    0.000000      0.000000   
25%    90243.500000      19318.500000   32.400000   9763.500000   
50%    90807.000000      31481.000000   37.100000  15283.000000   
75%    91417.000000      44978.000000   41.000000  22219.500000   
max    93591.000000     105549.000000   74.000000  52794.000000   

       Total Females  Total Households  Average Household Size  
count     319.000000        319.000000              319.000000  
mean    16849.777429      10964.570533                2.828119  
std     10934.986468       6270.646400                0.835658  
min         0.000000          0.000000                0.000000  
25%      9633.500000       6765.500000                2.435000  
50%     16202.000000      10968.000000                2.830000  
75%     22690.500000      14889.500000                3.320000  
max     53185.000000      31087.000000                4.670000  

 

Pandas 基于 NumPy 开发,所以任何时候你都可以通过 .values 将 DataFrame 转换为 NumPy 数组。

df.values  
==>
array([[9.1371e+04, 1.0000e+00, 7.3500e+01, ..., 1.0000e+00, 1.0000e+00,1.0000e+00],
       [9.0001e+04, 5.7110e+04, 2.6600e+01, ..., 2.8642e+04, 1.2971e+04,4.4000e+00],
       [9.0002e+04, 5.1223e+04, 2.5500e+01, ..., 2.6347e+04, 1.1731e+04,4.3600e+00],
         ...,
       [9.3560e+04, 1.8910e+04, 3.2400e+01, ..., 9.4190e+03, 6.4690e+03, 2.9200e+00],
       [9.3563e+04, 3.8800e+02, 4.4500e+01, ..., 1.2500e+02, 1.0300e+02,2.5300e+00],
       [9.3591e+04, 7.2850e+03, 3.0900e+01, ..., 3.6320e+03, 1.9820e+03,3.6700e+00]])

这也就说明了,你可以同时使用 Pandas 和 NumPy 提供的 API 对同一数据进行操作,并在二者之间进行随意转换。这就是一个非常灵活的工具生态圈。

 

除了 .values,DataFrame 支持的常见属性可以通过 官方文档相应章节 查看。其中常用的有:

df.index # 查看索引RangeIndex(start=0, stop=319, step=1)
df.columns # 查看列名 Index(['Zip Code', 'Total Population', 'Median Age', 'Total Males', 'Total Females', 'Total Households', 'Average Household Size'], dtype='object')
df.shape # 查看形状 (319, 7)

 

5.数据选择

在数据预处理过程中,我们往往会对数据集进行切分,只将需要的某些行、列,或者数据块保留下来,输出到下一个流程中去。这也就是所谓的数据选择,或者数据索引。

由于 Pandas 的数据结构中存在索引、标签,所以我们可以通过多轴索引完成对数据的选择。

(1)基于索引数字选择

当我们新建一个 DataFrame 之后,如果未自己指定行索引或者列对应的标签,那么 Pandas 会默认从 0 开始以数字的形式作为行索引,并以数据集的第一行作为列对应的标签。其实,这里的「列」也有数字索引,默认也是从 0 开始,只是未显示出来。

所以,我们首先可以基于数字索引对数据集进行选择。这里用到的 Pandas 中的 .iloc 方法。该方法可以接受的类型有:

1) 整数。例如:5 2) 整数构成的列表或数组。例如:[1, 2, 3] 3) 布尔数组。 4) 可返回索引值的函数或参数。

首先,我们可以选择前 3 行数据。

df.iloc[:3]  
==>  
     Zip Code  Total Population  Median Age  Total Males  Total Females  \
0     91371                 1        73.5            0              1   
1     90001             57110        26.6        28468          28642   
2     90002             51223        25.5        24876          26347   

   Total Households  Average Household Size  
0                 1                    1.00  
1             12971                    4.40  
2             11731                    4.36  
df.iloc[5]  
==> 
Zip Code                         90005.0
Total Population                 37681.0
Median Age                       33.9
Total Males                      19299.0
Total Females                    18382.0
Total Households                 15044.0
Average Household Size           2.5
Name: 5, dtype: float64

df.iloc[] 的 [[行],[列]] 里面可以同时接受行和列的位置,如果你直接键入 df.iloc[1, 3, 5] 就会报错。df.iloc[[]],选择多行数据

df.iloc[[1, 3, 5]] 
==>
   Zip Code  Total Population  Median Age  Total Males  Total Females  \
1     90001             57110        26.6        28468          28642   
3     90003             66266        26.3        32631          33635   
5     90005             37681        33.9        19299          18382   

   Total Households  Average Household Size  
1             12971                    4.40  
3             15642                    4.22  
5             15044                    2.50  

选择行学会以后,选择列就应该能想到怎么办了。例如,我们要选择第 2-4 列。

df.iloc[:, 1:4]  
==> 
         Total Population  Median Age  Total Males
0                   1        73.5            0
1               57110        26.6        28468
2               51223        25.5        24876
3               66266        26.3        32631
4               62180        34.8        31302
..                ...         ...          ...
314             38158        28.4        18711
315              2138        43.3         1121
316             18910        32.4         9491
317               388        44.5          263
318              7285        30.9         3653

[319 rows x 3 columns]

这里选择 2-4 列,输入的却是 1:4。这和 Python 或者 NumPy 里面的切片操作非常相似。既然我们能定位行和列,那么只需要组合起来,我们就可以选择数据集中的任何数据了。

(2)基于标签名称选择

除了根据数字索引选择,还可以直接根据标签对应的名称选择。这里用到的方法和上面的 iloc 很相似,少了个 i 为 df.loc[]。

df.loc[] 可以接受的类型有: 1) 单个标签。例如:2 或 'a',这里的 2 指的是标签而不是索引位置。 2) 列表或数组包含的标签。例如:['A', 'B', 'C']。 3) 切片对象。例如:'A':'E',注意这里和上面切片的不同支持,首尾都包含在内。 4) 布尔数组。 5) 可返回标签的函数或参数。

先选择前 3 行:

df.loc[0:2]  
==>
     Zip Code  Total Population  Median Age  Total Males  Total Females  \
0     91371                 1        73.5            0              1   
1     90001             57110        26.6        28468          28642   
2     90002             51223        25.5        24876          26347   

   Total Households  Average Household Size  
0                 1                    1.00  
1             12971                    4.40  
2             11731                    4.36  

再选择 1,3,5 行:

df.loc[[0, 2, 4]] 
==>
    Zip Code  Total Population  Median Age  Total Males  Total Females  \
0     91371                 1        73.5            0              1   
2     90002             51223        25.5        24876          26347   
4     90004             62180        34.8        31302          30878   

   Total Households  Average Household Size  
0                 1                    1.00  
2             11731                    4.36  
4             22547                    2.73 

然后,选择 2-4 列:

df.loc[:, 'Total Population':'Total Males']  
==>
     Total Population  Median Age  Total Males
0                   1        73.5            0
1               57110        26.6        28468
2               51223        25.5        24876
3               66266        26.3        32631
4               62180        34.8        31302
..                ...         ...          ...
314             38158        28.4        18711
315              2138        43.3         1121
316             18910        32.4         9491
317               388        44.5          263
318              7285        30.9         3653

[319 rows x 3 columns]

最后,选择 1,3 行和 Median Age 后面的列:

df.loc[[0, 2], 'Median Age':]  
==>
   Median Age  Total Males  Total Females  Total Households    Average Household Size
0        73.5            0              1                 1            1.00 
2        25.5        24876          26347             11731            4.3

 

6.数据删减

虽然我们可以通过数据选择方法从一个完整的数据集中拿到我们需要的数据,但有的时候直接删除不需要的数据更加简单直接。Pandas 中,以 .drop 开头的方法都与数据删减有关。

DataFrame.drop 可以直接去掉数据集中指定的列和行。一般在使用时,我们指定 labels 标签参数,然后再通过 axis 指定按列或按行删除即可。当然,你也可以通过索引参数删除数据,具体查看官方文档。

df.drop(labels=['Median Age', 'Total Males'], axis=1)
==> 
     Zip Code  Total Population  Total Females  Total Households  \
0       91371                 1              1                 1   
1       90001             57110          28642             12971   
2       90002             51223          26347             11731   
3       90003             66266          33635             15642   
4       90004             62180          30878             22547   
..        ...               ...            ...               ...   
314     93552             38158          19447              9690   
315     93553              2138           1017               816   
316     93560             18910           9419              6469   
317     93563               388            125               103   
318     93591              7285           3632              1982   

     Average Household Size  
0                      1.00  
1                      4.40  
2                      4.36  
3                      4.22  
4                      2.73  
..                      ...  
314                    3.93  
315                    2.62  
316                    2.92  
317                    2.53  
318                    3.67  

[319 rows x 5 columns]

DataFrame.drop_duplicates 则通常用于数据去重,即剔除数据集中的重复值。使用方法非常简单,指定去除重复值规则,以及 axis 按列还是按行去除即可。

df.drop_duplicates()  
==> 
     Zip Code  Total Population  Median Age  Total Males  Total Females  \
0       91371                 1        73.5            0              1   
1       90001             57110        26.6        28468          28642   
2       90002             51223        25.5        24876          26347   
3       90003             66266        26.3        32631          33635   
4       90004             62180        34.8        31302          30878   
..        ...               ...         ...          ...            ...   
314     93552             38158        28.4        18711          19447   
315     93553              2138        43.3         1121           1017   
316     93560             18910        32.4         9491           9419   
317     93563               388        44.5          263            125   
318     93591              7285        30.9         3653           3632   

     Total Households          Average Household Size  
0                   1                    1.00  
1               12971                    4.40  
2               11731                    4.36  
3               15642                    4.22  
4               22547                    2.73  
..                ...                     ...  
314              9690                    3.93  
315               816                    2.62  
316              6469                    2.92  
317               103                    2.53  
318              1982                    3.67  

[319 rows x 7 columns]

除此之外,另一个用于数据删减的方法 DataFrame.dropna 也十分常用,其主要的用途是删除缺少值,即数据集中空缺的数据列或行。

df.dropna() 
==>  
     Zip Code  Total Population  Median Age  Total Males  Total Females  \
0       91371                 1        73.5            0              1   
1       90001             57110        26.6        28468          28642   
2       90002             51223        25.5        24876          26347   
3       90003             66266        26.3        32631          33635   
4       90004             62180        34.8        31302          30878   
..        ...               ...         ...          ...            ...   
314     93552             38158        28.4        18711          19447   
315     93553              2138        43.3         1121           1017   
316     93560             18910        32.4         9491           9419   
317     93563               388        44.5          263            125   
318     93591              7285        30.9         3653           3632   

     Total Households          Average Household Size  
0                   1                    1.00  
1               12971                    4.40  
2               11731                    4.36  
3               15642                    4.22  
4               22547                    2.73  
..                ...                     ...  
314              9690                    3.93  
315               816                    2.62  
316              6469                    2.92  
317               103                    2.53  
318              1982                    3.67  

[319 rows x 7 columns]

 

7.数据填充

Pandas 为了更方便地检测缺失值,将不同类型数据的缺失均采用 NaN 标记。这里的 NaN 代表 Not a Number,它仅仅是作为一个标记。例外是,在时间序列里,时间戳的丢失采用 NaT 标记。

Pandas 中用于检测缺失值主要用到两个方法,分别是:isna() 和 notna(),故名思意就是「是缺失值」和「不是缺失值」。默认会返回布尔值用于判断。

接下来,我们人为生成一组包含缺失值的示例数据。

df = pd.DataFrame(np.random.rand(9, 5), columns=list('ABCDE'))

插入 T 列,并打上时间戳

df.insert(value=pd.Timestamp('2017-10-1'), loc=0, column='Time')

将 1, 3, 5 列的 1,3,5 行置为缺失值

df.iloc[[1, 3, 5, 7], [0, 2, 4]] = np.nan

将 2, 4, 6 列的 2,4,6 行置为缺失值

df.iloc[[2, 4, 6, 8], [1, 3, 5]] = np.nan
df  ==>  
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1        NaT  0.499374       NaN  0.834719       NaN  0.159916
2 2017-10-01       NaN  0.324404       NaN  0.457944       NaN
3        NaT  0.384484       NaN  0.582782       NaN  0.146258
4 2017-10-01       NaN  0.924983       NaN  0.620041       NaN
5        NaT  0.530039       NaN  0.447082       NaN  0.738411
6 2017-10-01       NaN  0.000739       NaN  0.213739       NaN
7        NaT  0.799279       NaN  0.271489       NaN  0.407514
8 2017-10-01       NaN  0.246225       NaN  0.644346       NaN

然后,通过 isna() 或 notna() 中的一个即可确定数据集中的缺失值。

df.isna()  ==>     
Time      A      B      C      D      E
0  False  False  False  False  False  False
1   True  False   True  False   True  False
2  False   True  False   True  False   True
3   True  False   True  False   True  False
4  False   True  False   True  False   True
5   True  False   True  False   True  False
6  False   True  False   True  False   True
7   True  False   True  False   True  False
8  False   True  False   True  False   True

上面已经对缺省值的产生、检测进行了介绍。实际上,面对缺失值一般就是填充和剔除两项操作。填充和清除都是两个极端。如果你感觉有必要保留缺失值所在的列或行,那么就需要对缺失值进行填充。如果没有必要保留,就可以选择清除缺失值。

其中,缺失值剔除的方法 dropna() 已经在上面介绍过了。下面来看一看填充缺失值 fillna() 方法。

首先,我们可以用相同的标量值替换 NaN,比如用 0。

print(df.fillna(0))  ==>
                  Time         A         B         C         D         E
0  2017-10-01 00:00:00  0.375561  0.509720  0.386046  0.942065  0.020290
1                    0  0.499374  0.000000  0.834719  0.000000  0.159916
2  2017-10-01 00:00:00  0.000000  0.324404  0.000000  0.457944  0.000000
3                    0  0.384484  0.000000  0.582782  0.000000  0.146258
4  2017-10-01 00:00:00  0.000000  0.924983  0.000000  0.620041  0.000000
5                    0  0.530039  0.000000  0.447082  0.000000  0.738411
6  2017-10-01 00:00:00  0.000000  0.000739  0.000000  0.213739  0.000000
7                    0  0.799279  0.000000  0.271489  0.000000  0.407514
8  2017-10-01 00:00:00  0.000000  0.246225  0.000000  0.644346  0.000000

除了直接填充值,我们还可以通过参数,将缺失值前面或者后面的值填充给相应的缺失值。例如使用缺失值前面的值进行填充:

df.fillna(method='pad')  ==> 
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1 2017-10-01  0.499374  0.509720  0.834719  0.942065  0.159916
2 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
3 2017-10-01  0.384484  0.324404  0.582782  0.457944  0.146258
4 2017-10-01  0.384484  0.924983  0.582782  0.620041  0.146258
5 2017-10-01  0.530039  0.924983  0.447082  0.620041  0.738411
6 2017-10-01  0.530039  0.000739  0.447082  0.213739  0.738411
7 2017-10-01  0.799279  0.000739  0.271489  0.213739  0.407514
8 2017-10-01  0.799279  0.246225  0.271489  0.644346  0.407514

或者是后面的值:

df.fillna(method='bfill')  ==>
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
2 2017-10-01  0.384484  0.324404  0.582782  0.457944  0.146258
3 2017-10-01  0.384484  0.924983  0.582782  0.620041  0.146258
4 2017-10-01  0.530039  0.924983  0.447082  0.620041  0.738411
5 2017-10-01  0.530039  0.000739  0.447082  0.213739  0.738411
6 2017-10-01  0.799279  0.000739  0.271489  0.213739  0.407514
7 2017-10-01  0.799279  0.246225  0.271489  0.644346  0.407514
8 2017-10-01       NaN  0.246225       NaN  0.644346       NaN

最后一行由于没有对于的后序值,自然继续存在缺失值。

上面的例子中,我们的缺失值是间隔存在的。那么,如果存在连续的缺失值是怎样的情况呢?试一试。首先,我们将数据集的第 2,4 ,6 列的第 3,5 行也置为缺失值。

df.iloc[[3, 5], [1, 3, 5]] = np.nan

然后来正向填充:

df.fillna(method='pad')  ==>
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1 2017-10-01  0.499374  0.509720  0.834719  0.942065  0.159916
2 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
3 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
4 2017-10-01  0.499374  0.924983  0.834719  0.620041  0.159916
5 2017-10-01  0.499374  0.924983  0.834719  0.620041  0.159916
6 2017-10-01  0.499374  0.000739  0.834719  0.213739  0.159916
7 2017-10-01  0.799279  0.000739  0.271489  0.213739  0.407514
8 2017-10-01  0.799279  0.246225  0.271489  0.644346  0.407514

可以看到,连续缺失值也是按照前序数值进行填充的,并且完全填充。这里,我们可以通过 limit= 参数设置连续填充的限制数量。

可以看到,连续缺失值也是按照前序数值进行填充的,并且完全填充。这里,我们可以通过 limit= 参数设置连续填充的限制数量。

df.fillna(method='pad', limit=1)  # 最多填充一项  ==>
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1 2017-10-01  0.499374  0.509720  0.834719  0.942065  0.159916
2 2017-10-01  0.499374  0.324404  0.834719  0.457944  0.159916
3 2017-10-01       NaN  0.324404       NaN  0.457944       NaN
4 2017-10-01       NaN  0.924983       NaN  0.620041       NaN
5 2017-10-01       NaN  0.924983       NaN  0.620041       NaN
6 2017-10-01       NaN  0.000739       NaN  0.213739       NaN
7 2017-10-01  0.799279  0.000739  0.271489  0.213739  0.407514
8 2017-10-01  0.799279  0.246225  0.271489  0.644346  0.407514

除了上面的填充方式,还可以通过 Pandas 自带的求平均值方法等来填充特定列或行。举个例子:

除了上面的填充方式,还可以通过 Pandas 自带的求平均值方法等来填充特定列或行。举个例子:

df.fillna(df.mean()['C':'E'])  ==>
        Time         A         B         C         D         E
0 2017-10-01  0.375561  0.509720  0.386046  0.942065  0.020290
1        NaT  0.499374       NaN  0.834719  0.575627  0.159916
2 2017-10-01       NaN  0.324404  0.497418  0.457944  0.195907
3        NaT       NaN       NaN  0.497418  0.575627  0.195907
4 2017-10-01       NaN  0.924983  0.497418  0.620041  0.195907
5        NaT       NaN       NaN  0.497418  0.575627  0.195907
6 2017-10-01       NaN  0.000739  0.497418  0.213739  0.195907
7        NaT  0.799279       NaN  0.271489  0.575627  0.407514
8 2017-10-01       NaN  0.246225  0.497418  0.644346  0.195907

对 C 列到 E 列用平均值填充。

 

8.插值填充

插值是数值分析中一种方法。简而言之,就是借助于一个函数(线性或非线性),再根据已知数据去求解未知数据的值。插值在数据领域非常常见,它的好处在于,可以尽量去还原数据本身的样子。

我们可以通过 interpolate() 方法完成线性插值。当然,其他一些插值算法可以阅读官方文档了解。

生成一个 DataFrame

df = pd.DataFrame({'A': [1.1, 2.2, np.nan, 4.5, 5.7, 6.9],
                   'B': [.21, np.nan, np.nan, 3.1, 11.7, 13.2]})
df ==>     
     A      B
0  1.1   0.21
1  2.2    NaN
2  NaN    NaN
3  4.5   3.10
4  5.7  11.70
5  6.9  13.20

对于上面存在的缺失值,如果通过前后值,或者平均值来填充是不太能反映出趋势的。这时候,插值最好使。我们用默认的线性插值试一试。

df_interpolate = df.interpolate()
df_interpolate  ==>
      A          B
0  1.10   0.210000
1  2.20   1.173333
2  3.35   2.136667
3  4.50   3.100000
4  5.70  11.700000
5  6.90  13.200000

下图展示了插值后的数据,明显看出插值结果符合数据的变化趋势。如果按照前后数据顺序填充,则无法做到这一点。 对于 interpolate() 支持的插值算法,也就是 method=。下面给出几条选择的建议: 1) 如果你的数据增长速率越来越快,可以选择 method='quadratic'二次插值。 2) 如果数据集呈现出累计分布的样子,推荐选择 method='pchip'。 3) 如果需要填补缺省值,以平滑绘图为目标,推荐选择 method='akima'。

当然,最后提到的 method='akima',需要你的环境中安装了 Scipy 库。除此之外,method='barycentric' 和 method='pchip' 同样也需要 Scipy 才能使用。

 

8.数据可视化

NumPy,Pandas,Matplotlib 构成了一个完善的数据分析生态圈,所以 3 个工具的兼容性也非常好,甚至共享了大量的接口。当我们的数据是以 DataFrame 格式呈现时,可以直接使用 Pandas 提供的 DataFrame.plot 方法调用 Matplotlib 接口绘制常见的图形。

例如,我们使用上面插值后的数据 df_interpolate 绘制线形图。

df_interpolate.plot()

输出图片:

其他样式的图形也很简单,指定 kind= 参数即可。

df_interpolate.plot(kind='bar')  #柱状图

输出图片:

 

9.其他用法

由于 Pandas 包含的内容实在太多,除了阅读完整的官方文档,很难做到通过一个实验或者一个课程进行全面了解。当然,本课程的目的是带大家熟悉 Pandas 的常用基础方法,至少你大致清楚了 Pandas 是什么,能干什么。

除了上面提到的一些方法和技巧,实际上 Pandas 常用的还有:

  • 数据计算,例如:DataFrame.add 等。

  • 数据聚合,例如:DataFrame.groupby 等。

  • 统计分析,例如:DataFrame.abs 等。

  • 时间序列,例如:DataFrame.shift 等。

posted on 2020-11-03 18:20  &起雾了  阅读(261)  评论(0编辑  收藏  举报

导航