pandas

pandas的数据结构

Series

  • Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。

  • 输出时:索引在左边,值在右边,如果没有指定索引,则自动创建0-N-1的整数型索引,可以通过series的value和index获取数组的表示形式和索引对象

  • 添加索引:在index参数中添加与数组同长度的数组,对各个数据点进行标记

  • 使用索引进行选取series的单个值或一组值

    • obj2['a']  # 单个值
      obj2[['a','b','c']]  # 一组值
  • 使用NumPy函数或类似NumPy的运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引值的链接

    • obj2[obj2 > 0]
      obj2 * 2
      np.exp(obj2)
  • 可以将series看成定长的有序字典,可以将其看成索引值到数据值的映射,可以用在许多原本需要字典参数的函数

    • # 使用字典创建series
      sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
      obj3 = pd.Series(sdata)
    • 如果只传入一个字典,则结果Series中的索引就是原字典的键(有序排列)。你可以传入排好序的字典的键以改变顺序:

    • states = ['California', 'Ohio', 'Oregon', 'Texas']
      obj4 = pd.Series(sdata, index=states)
    • 如果传入的index在是sdata中没有找到对应的值,则其结果的值就会为NAN(表示缺失或NA值),如果sdata中有值,而索引未传入,则直接从结果中抹除

  • pandas的isnullnotnull函数可用于检测缺失数据

    • pd.isnull(obj4)
      pd.notnull(obj4)
  • series中最重要的一个功能:能根据运算的索引标签自动对齐数字,类似于数据库的join方法

  • series对象本身与其索引都有一个name属性

  • series的索引可以通过赋值的方式就地修改,必须修改全部的索引,不能部分修改

    • obj = pd.Series([4,7,-5,3],index=range(4))
      # 0    4
      # 1    7
      # 2   -5
      # 3    3
      # dtype: int64
      obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']  # 正确的
      # Bob      4
      # Steve    7
      # Jeff    -5
      # Ryan     3
      # dtype: int64
      obj.index[0] = 1  # 错误的

Dataframe

  • DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。

  • 建DataFrame:

    • 直接传入一个有等长列表或NumPy数组组成的字典

      data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
              'year': [2000, 2001, 2002, 2001, 2002, 2003],
              'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
      frame = pd.DataFrame(data)
    • 使用嵌套字典:

      • 如果使用嵌套字典,则pandas会被解释为:外层的键作为列,内层的键作为行索引

    • 其他:pandas_第1张图片

  • head方法:

    • # head方法会选取前5行数据
      frame.head()
  • 建立DataFrame时,如果传入列序列,在DataFrame的列就会按照指定顺序进行排列

    • pd.DataFrame(data, columns=['year', 'state', 'pop'])
    • 如果传入的列在数据中找不到,则会在结果中产生缺失值

  • 通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series

  • 列也可以通过复制的方式进行修改

    • frame2['debt'] = 16.5
  • 当使用列表或数组进行赋值给某列时,其长度必须与DataFrame的长度相匹配,如果赋值的是Series,则会精确匹配DataFrame的索引。如果为不存在的列赋值则会创建出一个新列,注:不能用frame.eastern创建新的列

  • del方法可以用来删除这列

  • 使用类似NumPy数组的方法,对DataFrame进行转置frame.T

  • 如果设置的DataFrame的index和columns的name属性,则这些信息会被显示出来

  • 与series一样,value属性会以二维ndarry的形式返回DataFrame中的数据

  • 如果DataFrame各列的数据类型不同,则值数组的的type会选用能兼容所有列的数据类型

索引对象

  • pandas的索引对象负者管理轴标签和其他元数据,构建Series和DataFrame时,所用到的任何数组或其他序列的标签都会被换成一个Index

  • Index对象是不可变的,因此用户不能对其进行修改

  • 不可变可以使Index对象在多个数据结构之间安全共享

  • 除了类似于数组,index也类似于一个固定大小的集合,但与Python不同的是,pandas的index可以包含重复的标签,选择重复的标签,会显示所有结果

        pandas_第2张图片

基本功能

重新索引

  • reindex()根据新索引进行重排,如果某个索引值当前不存在,就引入缺失值

    • method='ffill' 实现前项值填充

  • 借助DataFrame,reindex可以修改(行)索引和列。只传递一个序列时,会重新索引结果的行,重新索引列时,用columns关键字重新索引

    pandas_第3张图片

丢弃指定轴上的项

  • 丢弃某条轴上的一个或多个项很简单,只要有一个索引数组或列表即可。由于需要执行一些数据整理和集合逻辑,所以drop方法返回的是一个在指定轴上删除了指定值的新对象

  • 对于DataFrame,可以删除任意轴上的索引值,不指定轴,则默认删除行标签(axis=0),要删除列的值,则传递axis=1或axis=columns

  • 可以就地修改对象,传入inplace=True

    • 小心使用inplace,它会销毁所有被删除的数据

索引、选取和过滤

  • Series索引的工作方式类似于Numpy数组的索引,只不过Series索引值不只是整数

    • obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
      obj['b']
      obj[1]
      obj[2:4]
      obj[['b', 'a', 'd']]
      obj[[1, 3]]
      obj[obj < 2]
  • 切片运算与Python切片不同,使用标签进行切片其末端是包含的obj['b':'c] 是包含c的,使用索引切片是不包含末端的obj[0:3],使用用切片可以对Series的相应部分进行设置

  • 用一个值或序列对DataFrame进行索引其实就是获取一个或多个列

  • 索引方式有几个特殊情况,首先通过切片或布尔型数组选取数据

    • data[:2]
      data[data['three'] > 5]

使用loc和iloc进行选取

  • 引入特殊的标签运算符loc和iloc,使用轴标签(loc)和整数索引(iloc)从DataFrame选择行和列的子集

    • data.loc['Colorado', ['two', 'three']]
    • data.iloc[2, [3, 0, 1]]

                pandas_第4张图片

整数索引

  • 对于整数索引与Python内置的列表和元组的索引语法不同

    • ser = pd.Series(np.arange(3.))
      ser
      ser[-1]  # error
    • 如果是非整数索引

    • ser2 = pd.Series(np.arange(3.), index=['a', 'b', 'c'])
      ser2[-1]  # 2.0
    • 如果轴索引含有整数,数据选取总会使用标签。为了更准确,请使用loc(标签)或iloc(整数)

算术运算和数据对齐

  • pandas最重要的一个功能是,它可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。对于有数据库经验的用户,这就像在索引标签上进行自动外连接

  • 自动的数据对齐操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播。对于DataFrame,对齐操作会同时发生在行和列上,其索引和列是原来两个DataFrame的并集

在算术方法中填充值

  • 使用算术运算,在没有重叠的位置会产生NA值,而使用填充值,避免NA值

    • In [165]: df1 = pd.DataFrame(np.arange(12.).reshape((3, 4)),
         .....:                    columns=list('abcd'))
      
      In [166]: df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)),
         .....:                    columns=list('abcde'))
      
      In [167]: df2.loc[1, 'b'] = np.nan
      
      In [168]: df1
      Out[168]: 
           a    b     c     d
      0  0.0  1.0   2.0   3.0
      1  4.0  5.0   6.0   7.0
      2  8.0  9.0  10.0  11.0
      
      In [169]: df2
      Out[169]: 
            a     b     c     d     e
      0   0.0   1.0   2.0   3.0   4.0
      1   5.0   NaN   7.0   8.0   9.0
      2  10.0  11.0  12.0  13.0  14.0
      3  15.0  16.0  17.0  18.0  19.0
      
      # 使用算术运算会出现NA值
      In [170]: df1 + df2
      Out[170]: 
            a     b     c     d   e
      0   0.0   2.0   4.0   6.0 NaN
      1   9.0   NaN  13.0  15.0 NaN
      2  18.0  20.0  22.0  24.0 NaN
      3   NaN   NaN   NaN   NaN NaN
      
      # 进行填充,避免出现NA值
      In [171]: df1.add(df2, fill_value=0)
      Out[171]: 
            a     b     c     d     e
      0   0.0   2.0   4.0   6.0   4.0
      1   9.0   5.0  13.0  15.0   9.0
      2  18.0  20.0  22.0  24.0  14.0
      3  15.0  16.0  17.0  18.0  19.0
  • 在Series和DataFrame中,都有一个副本,以字母r开头,他会翻转参数,

    • 1/df1 等价于 df1.rdiv(1))

    • pandas_第5张图片

DataFrame和Series之间的运算

  • DataFrame和Series之间会进行广播运算

  • 默认情况下,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着行一直向下广播

  • 如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集

  • 在列上广播,则必须使用算术运算方法

    • frame.sub(series3, axis='index')

函数应用和映射

  • NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象

    • frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),index=['Utah', 'Ohio', 'Texas', 'Oregon'])
      np.abs(frame)
  • 将函数应用到由各列或行所形成的一维数组上

    • f = lambda x: x.max() - x.min()
      frame.apply(f)# 在每列中执行一次,
      frame.apply(f,axis='columns')# 在每行中执行一次
    • 传递到apply的函数不是必须返回一个标量,还可以返回由多个值组成的Series

  • 将函数应用到元素

    • applymap() 将函数应用到元素上

      format = lambda x: '%.2f' % x
      frame.applymap(format)

排序和排名

  • 使用sort_index方法,返回一个已排序的新对象

  • 对于Series,使用sort_index可以根据index排序

  • 对于DataFrame,使用sort_index可以根据传入参数(axis)来对任意轴的索引进行排序

  • 数据默认是升序,但也可以是降序排列ascending=False

  • 若要按值进行排序,sort_values

  • 任何缺失值都会默认放到Series末尾,当排序DataFrame时,根据一个或多个列中的值进行排序,那就将一个或多个值的名字传递给sort_values中的by选项,多个值时,先对前一个排序,若其中有相等的,再根据第二个值排序

  • rank方法:默认情况下,rank是通过“为各组分配一个平均排名”的方式破坏平级关系的

    • 默认使用average,即有相同排名时,取其排名的平均值

    • min 对于相等的值,取较小的排名

    • max 对于相等的值,取较大的排名

    • first 对于相等的值,取最先出现的排名

    • dense类似于 ”min“,但排名不会出现大于 1 的空隙

带有重复标签的轴索引

  • 索引的is_unique属性,用来判断它的值是否唯一

  • 如果索引对应多个值,则会返回一个Series,而对应单个的值,则返回一个标量值,

汇总和计算描述统计

  • NA值会自动被排除,除非整个切片(这里指的是行或列)都是NA,通过skipna选项可以禁用该功能

    • pandas_第6张图片

    • pandas_第7张图片

相关系数和协方差

  • Series的corr方法用于计算两个Series中重叠的、非NA的、按索引对齐的值的相关系数。与此类似,cov用于计算协方差

  • DataFrame的corr和cov方法将以DataFrame的形式分别返回完整的相关系数或协方差矩阵

  • DataFrame的corrwith方法,计算其列或行跟另一个Series或DataFrame之间的相关系数。传入一个Series将会返回一个相关系数值Series(针对各列进行计算)

唯一性、值计数以及成员资格

  • unique得到Series中唯一值数组

  • value_counts用于计算一个Series中各值出现的频率,可用于任何数组或序列

  • isin判断矢量化集合的成员资格,可用于过滤Series中或DataFrame列中数据的子

  • index.get_indexer与isin类似的是Index.get_indexer方法,它可以给你一个索引数组,从可能包含重复值的数组到另一个不同值的数组

  • pandas_第8张图片

pandas数据加载、存储与文件格式

读取文本格式的数据

pandas_第9张图片

  • 函数选项的大致分类

    • 索引:将一个或多个列当做返回的DataFrame处理,以及是否从文件、用户获取列名。

    • 类型推断和数据转换:包括用户定义值的转换、和自定义的缺失值标记列表等。

    • 日期解析:包括组合功能,比如将分散在多个列中的日期时间信息组合成结果中的单个列。

    • 迭代:支持对大文件进行逐块迭代。

    • 不规整数据问题:跳过一些行、页脚、注释或其他一些不重要的东西(比如由成千上万个逗号隔开的数值数据)。

  • sep='分隔符' 指定分隔符

  • header=None 让pandas为其分配默认的列名

    • 可以自己定义列名name=['a', 'b', 'c', 'd', 'message']

    • 如果希望message列作为索引,可以明确表示要将该列放到索引4的位置上,也可以通过index_col参数指定"message"

  • 做一个层次化索引,传入由列编号,或列名组成的列表即可

    • parsed = pd.read_csv('examples/csv_mindex.csv',index_col=['key1', 'key2'])
  • 传入正则表达式作为分隔符

    • result = pd.read_table('examples/ex3.txt', sep='\s+')

  • 跳过文件的某些行

    • pd.read_csv('examples/ex4.csv', skiprows=[0, 2, 3]) 跳过文件的第一、三、四行

  • 对某些值进行标记,将其标记为NA值

    • 使用列表或集合的字符串表示缺失值

    • result = pd.read_csv('examples/ex5.csv', na_values=['NULL'])  # 将NULL值标记为NA值
    • 字典的各列可以使用不同的NA标记值

    • sentinels = {'message': ['foo', 'NA'], 'something': ['two']}
    • pandas_第10张图片

逐块获取文本文件

  • 看大文件之前,将pandas显示的更急一些

    • 显示10行数据

    • pd.options.display.max_rows = 10

    • 只读取几行数据

    • pd.read_csv('examples/ex6.csv', nrows=5)
  • 逐块读取文件【通过指定chunksize】

    • chunker = pd.read_csv('ch06/ex6.csv', chunksize=1000)

    • 返回TextParser对象,可以进行迭代

    • tot = pd.Series([])
      for piece in chunker:
          tot = tot.add(piece['key'].value_counts(), fill_value=0)

将数据写入到文本格式中

  • 利用DataFrame的to_csv方法将数据写到一个以逗号分隔的文件中

    • sep='字符串'可以指定其他分隔符

    • 缺失值会被标记为空字符串,也可以标记为其他的标记值na_rep="NULL"使用na_rep将缺失值标记为NULL

    • 如果没有设置其他选项,会写出行和列的标签,也可以进行禁用index=False,header=False

    • 也可以只写出部分列data.to_csv(sys.stdout, index=False, columns=['a', 'b', 'c'])不写入索引,并且只写入列为a,b,c,并且按写入的顺序排列

  • Series也有to_csv方法

处理分隔符格式

  • 对于任何单字符分隔符文件,直接使用Python内置的CSV模块,将任意已打开的文件或文件型对象传给csv.reader,对reader进行迭代会为每行产生一个元组,并移除了所有引号

  • pandas_第11张图片

JSON数据

  • 已经成为通过HTTP请求在Web浏览器和其他应用程序之间发送数据的标准格式之一。它是一种比表格型文本格式(如CSV)灵活得多的数据格式。

  • json.loads(obj)实现将JSON字符串转换为Python形式

  • json.dumps(obj) 实现将Python对象转化为JSON格式

  • pandas.read_json 可以自动将特别的JSON数据集转化为Series或DataFrame

  • to_json 方法:将数据从pandas输出到JSON

二进制数据格式

  • 实现数据的高效二进制格式存储最简单的办法之一是使用Python内置的pickle序列化

  • pandas对象都有一个用于将数据以pickle格式保存到磁盘上的to_pickle方法

    • frame.to_pickle('examples/frame_pickle')

  • 可以通过pickle直接读取被pickle化的数据,或是使用更为方便的pandas.read_pickle

    • pd.read_pickle('examples/frame_pickle')

读取Microsoft Excel文件

  • pandas的ExcelFile类或pandas.read_excel函数支持读取存储在Excel 2003(或更高版本)中的表格型数据。这两个工具分别使用扩展包xlrd和openpyxl读取XLS和XLSX文件。你可以用pip或conda安装它们

    • 要使用ExcelFile,通过传递xls或xlsx路径创建一个实例

    • xlsx = pd.ExcelFile('examples/ex1.xlsx')

  • 使用read_excel读取到DataFrame中

    • pd.read_excel(xlsx, 'Sheet1')

  • 将pandas数据写入为Excel格式

    • 首先创建一个ExcelWriter,然后使用pandas对象的to_excel方法将数据写入其中

    • writer = pd.ExcelWriter('examples/ex2.xlsx')
      frame.to_excel(writer, 'Sheet1')
      writer.save()
    • 也可以不使用ExcelWriter,而是直接传递文件的路径到to_excel

    • frame.to_excel('examples/ex2.xlsx')

数据清洗和准备

处理缺失数据

  • pandas使用浮点值NaN表示缺失数据

  • Python内置的None值在对象数组中也可以作为NA值

  • pandas_第12张图片

滤除缺失数据

  • 对于series

    • 可以通过pandas.isnull或布尔索引的手工方法

      • dropna会更实用一些,并且返回一个含非空数据和索引值的Series

        • data.dropna()
          # 等价于
          data[data.notnull()]
  • 对于DataFrame

    • dropna()默认丢弃任何含有缺失值的行

    • 指定axis=1丢弃任何含有缺失值的列

    • how='all' 只丢弃那些全为NA的行或列

    • thesh=2 保留至少2行,留下一部分观测数据

填充缺失值

  • fillna()方法通过一个常数调用fillna将缺失值替换为常数

    • 通过调用fillna() 可以实现对不同的列填充不同的值

    • fillna会返回新对象,但也可以对现有对象进行就地修改

    • reindexing有效的插值方法也可用于fillna()

      • df.fillna(method='ffill')# 向前填充

      • df.fillna(method='ffill', limit=2)向前填充,限制为2

数据转换

移除重复数据

  • DataFrame的duplicated()返回一个布尔型Series,表示各行是否是重复的行(前面出现过的行)

    • data.duplicated()

    • drop_duplicates()返回一个一个DataFrame,重复的数组会标为False

    • 默认判断全部列,可以指定部分列进行重复项判断data.drop_duplicates(['k1'])根据k1列过滤重复项

    • 默认保存的是第一次出现的值组合,传入keep='last'则保留最后一个

利用函数或映射进行数据转换

  • map()函数

  • Series的str.lower()将各个值转换为小写

  • data['animal'] = lowercased.map(meat_to_animal) animal是新建的列,meat_to_animal是不同肉类到动物的映射

  • 也可以传入函数

    • data['food'].map(lambda x: meat_to_animal[x.lower()])

替换值

  • 利用replace来产生一个新的Series(除非传入inplace=True)

    • data.replace(-999, np.nan)

    • 将-999替换为NaN

    • 如果需要一次性替换多个值,传入一个待替换组成的列表以及一个替换值

    • data.replace([-999, -1000], np.nan)

    • 如果要每个值的替换值都不一样则传入一个替换列表

    • data.replace([-999, -1000], [np.nan,0])

    • 也可以传入字典

    • data.replace({-999: np.nan, -1000: 0})

重命名轴索引

  • 跟Series中的值一样,轴标签也可以通过函数或映射进行转换,从而得到一个新的不同标签的对象。轴还可以被就地修改,而无需新建一个数据结构

  • data.index.map()

  • 将其传给data.index可以实现就地修改

    • data.index = data.index.map()

  • 想要创建数据集的转换版(而不是修改原始数据)比较实用的是rename()

    • 可以结合字典型对象实现对部分轴标签的更新

  • rename可以实现复制DataFrame并对其索引和列标签进行赋值。如果希望就地修改某个数据集,传入inplace=True即可

    • data.rename(index={'OHIO': 'INDIANA'}, inplace=True)将OHIO修改为INDIANA

离散化和面元划分

  • 使用cut()将数据划分

    • bins = [18, 25, 35, 60, 100]
      cats = pd.cut(ages, bins)
    • pandas返回的是一个特殊的Categorical对象

    • codes属性中的年龄数据的标签

      • cats.codes
        # array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8)
    • pd.value_counts(cats)是pandas.cut结果的面元计数。

    • 跟“区间”的数学符号一样,圆括号表示开端,而方括号则表示闭端(包括)。哪边是闭端可以通过right=False进行修改

    • 可 以通过传递一个列表或数组到labels,设置自己的面元名称

      • group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
        pd.cut(ages, bins, labels=group_names)
    • 如果向cut传入的是面元的数量而不是确切的面元边界,则它会根据数据的最小值和最大值计算等长面元

      • data = np.random.rand(20)
        pd.cut(data, 4, precision=2)
        # [(0.34, 0.55], (0.34, 0.55], (0.76, 0.97], (0.76, 0.97], (0.34, 0.55], ..., (0.34, 0.55], (0.34, 0.55], (0.55, 0.76], (0.34, 0.55], (0.12, 0.34]]
        # Length: 20
        # Categories (4, interval[float64]): [(0.12, 0.34] < (0.34, 0.55] < (0.55, 0.76] < (0.76, 0.97]]
      • precision=2限制小数只有两位

  • 使用qcut()

    • 根据样本分位数对数据进行面元划分

    • cut可能无法使各个面元中含有相同数量的数据点。而qcut由于使用的是样本分位数,因此可以得到大小基本相等的面元

检测和过滤异常值

  • 选出全部含有“超过3或-3的值”的行,你可以在布尔型DataFrame中使用any方法

    • data[(np.abs(data) > 3).any(1)]显示data中行有绝对值大于3的行

    • data[(np.abs(data) > 3).any(1)]对值进行设置,将值限制在-3到3之间

排列和随机采样

  • 利用numpy.random.permutation函数可以轻松实现对Series或DataFrame的列的排列工作(permuting,随机重排序)

  • 然后就可以在基于iloc的索引操作或take函数中使用该数组了

  • df = pd.DataFrame(np.arange(5 * 4).reshape((5, 4)))  # 创建数组
    sampler = np.random.permutation(5)  # 创建随机数组
    df.take(sampler)  #使用take使用随机数组进行排列
  • 选取随机子集,在Series和DataFrame上使用sample()

  • 要通过替换的方式产生样本(允许重复选择),可以传递replace=True到sample

    • choices = pd.Series([5, 7, -1, 6, 4])
      draws = choices.sample(n=10, replace=True)

计算指标/哑变量

  • 常用于统计建模或机器学习的转换方式是:将分类变量(categorical variable)转换为“哑变量”或“指标矩阵”

  • 如果DataFrame的某一列中含有k个不同的值,则可以派生出一个k列矩阵或DataFrame(其值全为1和0)。pandas有一个get_dummies函数可以实现该功能(其实自己动手做一个也不难)。使用之前的一个DataFrame例子

    • df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],'data1': range(6)})
      pd.get_dummies(df['key'])
  • DataFrame的列加上一个前缀,以便能够跟其他数据进行合并,get_dummies的prefix参数可以实现该功能

字符串操作

字符串对象方法

pandas_第13张图片

pandas的矢量化字符串函数

  • 通过data.map,所有字符串和正则表达式方法都能被应用于(传入lambda表达式或其他函数)各个值,但是如果存在NA(null)就会报错

  • data.str.contains('gmail') 通过str.contains检查各个电子邮件地址是否含有"gmail"

  • pandas_第14张图片

你可能感兴趣的:(python,开发语言)