python笔记:pandas基本使用

在python中,Pandas可以说是最实用的库之一,它提供了非常丰富的数据读写方法。可以看一下Pandas中文网提供的Pandas参考文档中对所有I/O函数的总结。

Pandas是一个开源的,BSD许可的库,为python提供高性能、易于使用的数据结构和数据分析工具。它的使用基础是Numpy(提供高性能的矩阵运算);可以用于数据挖掘和数据分析,同时也提供数据清洗的功能。
本文就对Pandas的基本使用做一个简单的归纳,所有代码可以从上往下按顺序依次执行。

References

电子文献:
https://www.cnblogs.com/chenhuabin/p/11477076.html
https://blog.csdn.net/weixin_39791387/article/details/81487549
https://kanoki.org/2019/09/16/dataframe-visualization-with-pandas-plot/
https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html
https://blog.csdn.net/weixin_41712499/article/details/82719987


csv

这里我想介绍一下一种新的数据格式:csv。它和excel很像,但又不同于excel。csv主要有如下特点:

  1. 纯文本,使用某个字符集,比如ASCII、Unicode、EBCDIC或GB2312(简体中文环境)等;
  2. 由记录组成(典型的是每行一条记录);
  3. 每条记录被分隔符(英语:Delimiter)分隔为字段(英语:Field (computer science))(典型分隔符有逗号、分号或制表符;有时分隔符可以包括可选的空格);
  4. 每条记录都有同样的字段序列。

在Pandas的使用以及AI相关竞赛数据集、结果的存储与使用中,csv文件往往承担着主角的位置。


准备

在具体使用之前,别忘了先导入所需相应的库。

1
2
import pandas as pd
import numpy as np

可以使用pd.__version__来输出版本号,注意,这里的“__”是两个“_”,这个很容易搞错且难以发现。


两大利器

Pandas中文网首页,在介绍完Pandas之后,就重点介绍了一下Pandas的两大利器。分别是DataFrame和Series。这里我先介绍一下Seires,DataFrame在后面有更详细的操作。

  1. Series简介

    Series是一种类似于一维数组的对象,是由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据也可产生简单的Series对象。
    我们可以通过传入一个list的数值来创建一个Series,Pandas会创建一个默认的整数索引:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    s = pd.Series([1, 3, 5, np.nan, 6, 8])

    s
    >>> 0 1.0
    1 3.0
    2 5.0
    3 NaN
    4 6.0
    5 8.0
    dtype: float64

    注:这里用np.nan来产生NaN,但要注意的是np.nan不是一个“空”对象,即使用np.nan == np.nan来判断将返回False,np.nan的类型为基本数据类型float。
    若要对某个值进行空值判断,如对np.nan,需要用np.isnan(np.nan),此时返回为True。

    另外,也可以从字典创建Series。

  2. DataFrame简介

    DataFrame是Pandas中的一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。
    我们可以通过传入一个numpy数组来创建一个DataFrame,如下面带有一个datetime的索引以及被标注的列:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    dates = pd.date_range('20130101', periods = 6)

    dates
    >>> DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
    '2013-01-05', '2013-01-06'],
    dtype = 'datetime64[ns]', freq = 'D')

    df1 = pd.DataFrame(np.random.randn(6, 4), index = dates, columns = list('ABCD'))

    df1
    >>> A B C D
    2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
    2013-01-02 1.212112 -0.173215 0.119209 -1.044236
    2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
    2013-01-04 0.721555 -0.706771 -1.039575 0.271860
    2013-01-05 -0.424972 0.567020 0.276232 -1.087401
    2013-01-06 -0.673690 0.113648 -1.478427 0.524988

    注:上面用pd.data_range()生成了一个时间频率freq = 'D'(即天)的日期序列。

    我们也可以通过传入一个可以转换为类Series(series-like)的字典对象来创建一个DataFrame:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    df2 = pd.DataFrame({'A': 1.,
    'B': pd.Timestamp('20130102'),
    'C': pd.Series(1, index = list(range(4)), dtype = 'float32'),
    'D': np.array([3] * 4, dtype = 'int32'),
    'E': pd.Categorical(["test", "train", "test", "train"]),
    'F': 'foo'})

    df2
    >>> A B C D E F
    0 1.0 2013-01-02 1.0 3 test foo
    1 1.0 2013-01-02 1.0 3 train foo
    2 1.0 2013-01-02 1.0 3 test foo
    3 1.0 2013-01-02 1.0 3 train foo

    这里可以使用df2.dtypes来查看不同列的数据类型。

读取

无论是txt文件还是csv文件,在Pandas中都使用read_csv()读取,当然也使用同一个方法写入到文件,那就是to_csv()方法。

1
df = pd.read_csv(abs_path) #此为绝对路径

为了提供更加多样化、可定制的功能,read_csv()方法定义了数十个参数,还在大部分参数并不常用,以下是几个比较常用的参数:

  1. filepath_or_buffer:文件所在路径,可以是一个描述路径的字符串、pathlib.Path对象、http或ftp的连接,也可以是任何可调用read()的对象。这是唯一一个必传的参数,也就是上面的abs_path。
  2. encoding:编码,字符型,通常为utf-8,如果中文读取不正常,可以将encoding设为gbk。当然,也可以直接将对应文件改成utf-8编码。
  3. header:整数或者由整数组成的列表,用来指定由哪一行或者哪几行作为列名,默认为header = 0,表示用第一列作为列名。若设置header = 0,则指定第二列作为列名。要注意的是,当指定第一行之后的数据作为列名时,前面的所有行都会被略过。也可以传递一个包含多个整数的列表给header,这样每一列就会有多个列名。如果中间某一行没有指定,那么该行会被略过。例如header = [0, 2],则原本的第二行会被省去。而当文件中没有列名一行数据时,可以传递header = None,表示不从文件数据中指定行作为列名,这时Pandas会自动生成从零开始的序列作为列名。
  4. names:接着上面的header,很快就想到是不是可以自己设置列名。names就可以用来生成一个列表,为数据额外指定列名。例如:df = pd.read_csv('abs_path, names=['第一列', '第二列', '第三列', '第四列'])

在数据读取完毕之后,我们可以使用如下代码来快速查看数据是否正确地导入了。

1
2
3
4
df.head() #看一下导入后df(DataFrame)的前几行,可在括号内输入数字来设定具体显示几行,默认5行
df.tail() #类似,查看后几行

type(df) #查看类型,DataFrame的输出应该是pandas.core.frame.DataFrame


DataFrame

DataFrame的介绍在前面的简介已经写过,这里就不赘述了。事实上,Pandas中的DataFrame的操作,有很大一部分跟numpy中的二维数组的操作是近似的。
在上面的读取处理之后,我们下面对其进行一些简单的操作:

  1. 查看

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    df.head() #上文已提及
    df.tail()

    #查看列名
    print(df.columns)

    #查看索引
    print(df.index)

    #查看各列的数据格式
    print(df.dtypes)

    #查看整个DataFrame的属性信息
    print(df.info())

    #访问对应行
    df.loc[0] #这里访问了第一行,将显示列名和对应每一列第一行的数据
    #具体有关索引请看后文
  2. 筛选

    在numpy中,我们可以这样判断一个数组中每一个数和对应数值的比较结果:

    1
    2
    a = np.array(range(10))
    a > 3

    输出将是一串布尔型(True、False)的array。
    而在DataFrame中,我们可以用类似的方法通过指定列来进行筛选:

    1
    2
    #筛选第二列中数值大于80
    df[df.第二列 > 80]

    这样就会得到只用符合条件数据的对应行的一个DataFrame。
    我们也可以使用df[(df.第一列 > 80) & (df.第二列 > 80) & (df.第三列 > 80)]来进行多条件的复杂筛选。
    此外,我们可以直接根据列名提取出一个新的表格:

    1
    new = df[['第一列', '第二列']] #new为仅由第一列和第二列组成的一个新的DataFrame
  3. 排序

    可以使用如下代码根据单列或者多列的值对数据进行排序:

    1
    2
    df.sort_values(['第二列', '第一列', '第三列'], ascending = [True, True, True])
    #使用df.sort_values(['第二列', '第一列', '第三列']).head()查看排序完后前几行的结果

    这里排序的规则是:根据设置的顺序(这里是先按第二列排),从小到大升序对所有数据进行排序。其中ascending是设置升序(默认True)和降序(False)。若仅选择单列,则无需添加[],这里[]的作用是把选择的行列转换为列表。

  4. 重命名

    如果觉得我前面取得列名称不好听,可以使用下面这个代码来改成需要的名字:

    1
    df.rename(columns = {'第一列': '好听的第一列', '第二列': '好听的第二列', '第三列': '好听的第三列', '第四列': '好听的第四列',}, inplace = True)

    这里用到了字典。

  5. 索引

    前面提到了使用索引来查看第一行,可当没有数字索引,例如我们通过df = pd.DataFrame(scores, index = ['one', 'two', 'three'])把index设为one、two、three时,df.loc[0]就失效了。因此有下面几种处理方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #访问index为“one”的行
    df.loc['one']

    #访问实实在在所谓的第几行(无论index为何)
    df.iloc[0] #注意0指的是第一行

    #ix合并了loc和iloc的功能,当索引为数字索引的时候,ix和loc是等价的
    df.ix[0] #访问第一行
    df.ix['one'] #访问“one”行,这里也指的是第一行
  6. 切片

    类似的,DataFrame也支持切片操作,但还是需要注意的。
    这里总结两种切片方式:

    1. 利用索引

      即使用df.loc[:2]ordf.ix[:2]等索引方式,这里这样的话输出为前三行。
    2. 直接切片

      这种方法只能在访问多行数据时使用,例如df[:2]将输出前两行,注意,这里比上面的方法要少一行。此外,值得强调的是,用这种方法访问单行数据是禁止的,例如不能使用df[0]来访问第一行数据。
  7. 插入

    上面的索引还有一种用途,就是可以用于插入指定index的新行。

    1
    df.loc['new_index'] = ['one', 'piece', 'is', 'true']
  8. 删除

    上面插入的那行中我说了“大秘宝是真实存在的”(海贼迷懂),下面我想把这句话所在的行删了,可以使用df.dtop()来完成。

    1
    df = df.drop('new_index')
  9. 数组

    我们可以使用df.第一列.values以array的形式输出指定列的所用值。
    基于此,我们可以使用df.第一列.value_counts()来做简单的统计,也就是对该列中每一个出现数字作频次的统计。
    我们还可以直接对DataFrame做计算,例如:df * n(n为具体数值),结果就是对表中的每一个数值都乘上对应的倍数。

  10. 元素操作

    1. map函数

      map()是python自带的方法, 可以对DataFrame某列内的元素进行操作。
      下面是一种使用实例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      def func(grade):
      if grade >= 80:
      return "A"
      elif grade >= 70:
      return "B"
      elif grade >= 60:
      return "C"
      else:
      return "D"

      df['评级'] = df.第一列.map(func)

      这样DataFrame后面会自动添加一列名为“评级”,并根据第一列来生成数据填入。

    2. apply函数

      当我们需要进行根据多列生成新的一个列的操作时,就需要用到apply。其用法简单示例如下:

      1
      df['求和'] = df.apply(lambda x: x.第一列 + x.第二列, axis = 1)
    3. applymap函数

      applymap时对dataframe中所有的数据进行操作的一个函数,非常重要。例如,我要让之前所用的score和grade都变成scroe+或者grade+,那么我就可以这样:

      1
      df.applymap(lambda x: str(x) + '+')

      如果是成绩单的话,那么这样操作之后打出来就会好看些啦,哈哈。

  11. plot

    数据可视化本来是一个非常复杂的过程,但Pandas数据帧plot函数的出现,使得创建可视化图形变得很容易。
    这个函数的具体使用可以访问文首给出的第三个参考链接,为一个印度小哥利用kaggle上的数据df.plot()做的一个非常详尽的介绍。
    有机会的话我会结合matplotlib对其做一个搬运与总结,先留个坑。
  12. 统计

    我们可以使用df.describe()对数据进行快速统计汇总。输出将包括:count、mean、std、min、25%、50%、75%和max。
    通过df.mean()我们可以按列求均值,如果想要按行求均值,可以使用df.mean(1)
  13. 高阶

    此外还有使用df.T进行转置,df.dropna(how = 'any')删除所有具有缺失值的数据,df.fillna(value = 5)填充所有缺失数据等高阶用法。详细的可以查阅前面给的参考链接10 minutes to pandas,至于更高阶的,可以看一下cookbook,不过一般还是在运用的过程中遇到需求再查找,一下子记不住那么多的。

写入

通过to_csv()可以将Pandas数据写入到文本文件中,和读取read_csv()类似,它也有几个常用参数:

  1. path_or_buf:表示路径的字符串或者文件句柄,也是必需的。例如:df.to_csv(abs_path)。要注意的是,这里如果abs_path对应的文件不存在,则会新建abs_path的同名文件后再写入,如果本来已存在该文件,则会自动清空该文件后再写入。
  2. sep:分隔符,默认为逗号。当写入txt文件时,就需要这个参数来确定数据之间的分隔符了。
  3. header:元素为字符串的列表或布尔型数据。当为列表时表示重新指定列名,当为布尔型时,表示是否写入列名。这和读取时的使用基本类似。
  4. columns:后接一个列表,用于重新指定写入文件中列的顺序。例如:df.to_csv(abs_path, columns = ['第四列', '第二列', '第三列', '第一列'])
  5. index_label:字符串或布尔型变量,设置索引列列名。原本的索引是空的,使用这个参数就可以给索引添加一个列名。如果觉得不需要添加,同时空着不好看(空的话还是会有分隔符),可以设置为False去掉(同时也将不显示分隔符)。
  6. index:布尔型,是否写入索引列,默认为True。
  7. encoding:写入时所用的编码,默认是utf-8。这个和上述的许多参数其实保持默认即可。

匿名函数

在上面DataFrame一节的最后,我用到了两个匿名函数,这里我想举个例子来简单展示一下匿名函数的使用方法,的确很好用!
当我们对一个数进行操作时,若使用函数,一般会:

1
2
def func(number):
return number + 10

这样看上去就有点费代码了,因此有下面的等价匿名函数可以替代:

1
func = lambda number: number + 10

当然假如想追求代码行数的话也不拦着你~


推荐

最近看到了DataWhale的一篇文章,也总结的挺好,在这里推荐一下。


碰到底线咯 后面没有啦

本文标题:python笔记:pandas基本使用

文章作者:高深远

发布时间:2020年01月13日 - 20:28

最后更新:2020年02月01日 - 17:35

原始链接:https://gsy00517.github.io/python20200113202851/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%