Python—Pandas基础学习

概述

Pandas是一个Python软件包,提供快速,灵活和富于表现力的数据结构。

Pandas建立在NumPy之上,旨在与许多其他第三方库在科学计算环境中很好地集成。

Pandas 的两个主要数据结构Series(一维)和DataFrame(二维),处理了金融,统计,社会科学和许多工程领域的绝大多数典型用例。

Pandas对许多不同种类的数据都非常适合,例如:

  • 具有不同类型列的制表数据,如SQL表或Excel电子表格中的数据

  • 有序和无序(不一定是固定频率)时间序列数据。

  • 具有行和列标签的任意矩阵数据(类型相同或异构)

  • 任何其他形式的观测/统计数据集。实际上,数据根本不需要标记就可以放入到pandas数据结构中

以下是Pandas非常擅长做的事:

  • 易于处理浮点数据和非浮点数据中的缺失数据(表示为NaN)
  • 大小可变性:可以从DataFrame和更高维的对象中插入和删除
  • 自动和显式的数据对齐:可以将对象显式地对齐到一组标签,或者用户可以简单地忽略标签并让Series,DataFrame等自动为您对齐数据
  • 强大,灵活的分组功能,可对数据集执行拆分应用合并操作,以汇总和转换数据
  • 便于将其他Python和NumPy数据结构中的不规则、不同索引的数据转换为DataFrame对象
  • 基于智能标签的切片花式索引和 大数据集子集
  • 直观的合并联接数据集
  • 灵活地重塑和旋转数据集
  • 轴的分层标签(每个刻度可能有多个标签)
  • 强大的IO工具,用于从平面文件(CSV和带分隔符),Excel文件,数据库中加载数据,以及从超快HDF5格式保存/加载数据
  • 特定于时间序列的功能:日期范围生成和频率转换,移动窗口统计信息,日期移动和滞后。



安装

方式一:Anaconda

Anaconda作为一个跨平台(Linux,Mac OS X,Windows)的一个开源的Python发行版本

不仅包含了Pandas,还包含了其他诸如NumPy、Matplotlib等大量软件包

下载方式

(这里推荐清华大学开源软件镜像站下载,点此跳转

方式二:Miniconda

Anaconda有一个缺点就是大,因为他会预先安装上百个软件包,其中很多或许你用不到,这时候Miniconda就用到了

Miniconda允许您创建一个最小的自包含Python安装,然后使用 Conda命令安装其他软件包。

下载方式

  1. (由于本人使用的是Anaconda,所以也不详细介绍Miniconda)
  2. 这里放一下安装地址

方式三: 从PyPI安装

打开cmd,使用命令行安装

命令:

pip install pandas

(注:由于pip使用的是国外的源,所以下载可能会很慢,可以使用清华源进行下载)

pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple



进入主题,开始入门

这里推荐大家使用Jupyter练习Python,当然也可以使用其他方式

导入方式

import pandas as pd
import numpy as np             #接下来的样例中需要用到NumPy库

对象创建

更多信息请参阅官方文档关于数据结构的简介

Series

Series是一维标记的数组,能够保存任何数据类型(整数,字符串,浮点数,Python对象等)。轴标签统称为索引

创建Series的基本方法是调用:

s = pd.Series(data,index=index)

参数data可以是一个Python字典,一个ndarray对象,或是常量值

参数index指数组的索引,如果没有传递索引,则创建一个具有值的索引[0,1,……,len(data)-1]

(如果data是ndarray对象,则索引的长度必须与data的长度相同)

举个栗子

#data:字典
d = {'d':1,'a':0,'c':2}
print("data:字典")
print(pd.Series(d))

#data:ndarray
d = np.random.randn(5)
print("data:ndaary")
print(pd.Series(d,['A','B','C','D','E']))

#data:常量值,必须提供索引,该值将重复以匹配index的长度;如果不提供,则index只会等于0
d = 5
print("data:constant")
print(pd.Series(d,[0,1,2,3,4]))

Series是一个ndarray-like

 Series和ndarray的作用非常类似,并且在大多数NumPy函数中Series都是一个有效的参数。

但是,例如切片操作也会对标签进行切片

举个栗子

s = pd.Series(np.random.randn(5))
#索引
print("索引")
print(s[0])
#切片
print("切片")
print(s[:3])
#布尔类型索引
print("布尔类型索引")
print(s[s>s.median()])
#索引数组建立建立索引
print("索引数组建立建立索引")
print(s[[1,4,3]])
#Series作为参数
print("Series作为参数")
print(np.exp(s))

如果要用到数组,请使用Series.array

s.array

如果要用到ndarray.请使用Series.to_numpy()

s.to_numpy()

使用Series进行矢量化操作和标签对齐

在Pandas中对Series进行操作时和NumPy一样,通常不需要逐值循环。Series也可以作为参数传递给NumPy方法

print("s+s:")
print(s+s)
print("s*2")
print(s*2)
print("np.exp(s)")
print(np.exp(s))

DataFrame

DataFrame是一个带有标签的二维数据结构,其中的列可能具有不同类型。它通常是最常用的pandas对象。

DataFrame接受多种不同类型的输入:

来自Series或dict的字典方式的DataFrame

d = {'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']),
     'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
df                    #空值使用NaN表示
pd.DataFrame(d,index=['d','b','a'])   #根据指定标签输出
pd.DataFrame(d,columns=['two','three'])   #根据指定列输出,如果没有,则用空值NaN表示

通过df.index和df.columns分别访问行标签和列表前

print(df.index)          #行标签
print(df.columns)        #列标签

来自ndrrays/list的字典

ndarray的长度必须相同,如果传递了索引,那它的长度显然也必须与数组相同;如果未传递索引,则结果为range(n),其中n为数组长度

d = {'one':[1,2,3,4],'two':[4,3,2,1]}
pd.DataFrame(d)

来自结构化或记录数组

data = np.zeros((2, ), dtype=[('A', 'i4'), ('B', 'f4'), ('C', 'a10')])  #初始化结构化数组
data[:] = [(1,2.,'Hello'),(2,3.,'World')]
pd.DataFrame(data)

来自字典列表

data2 = [{'a':1,'b':2},{'a':5,'b':10,'c':20}]
pd.DataFrame(data2)

来自元组的字典

#这样排列纯粹为了方便看点
pd.DataFrame({
               ('一', 'b'): 
                            {('三', 'B'): 1, ('三', 'C'): 2},
               ('一', 'a'): 
                            {('三', 'C'): 3, ('三', 'B'): 4},
               ('一', 'c'): 
                            {('三', 'B'): 5, ('三', 'C'): 6},
               ('二', 'a'): 
                            {('三', 'C'): 7, ('三', 'B'): 8},
               ('二', 'b'): 
                            {('三', 'D'): 9, ('三', 'B'): 10}})

来自Series

s1 = pd.Series(np.random.randn(5),index=['a','b','c','d','e'])
s2 = pd.Series(np.random.randn(5),index=['a','b','c','d','e'])
df = pd.DataFrame((s1,s2))

df

列的选择,添加,删除

#选择
df['e']
#添加
df['f']=df['a']+df['b']
df['flag'] = df['c'] > 0
df
#删除的两种方式
del df['d']
e = df.pop('e')
df
#插入
#三个参数:
#第一个:插入的位置
#第二个:插入的列名
#第三个:插入的值
df.insert(1,'z',df['a'])
df

必要的基本功能

先创建一些示例对象

import pandas as pd
import numpy as np
index = pd.date_range('1/1/2000',periods=8)
s = pd.Series(np.random.randn(5),index=['a','b','c','d','e'])
df = pd.DataFrame(np.random.randn(8,3),index = index)
print(index)
print(s)
print(df)

查看head和tail

默认显示的元素数量为5,但是可以传递自定义的数字

long_series = pd.Series(np.random.randn(1000))
print("long_series.head():")
print(long_series.head())
print("long_series.tail():")
print(long_series.tail(1))

加速操作

 pandas支持使用numexpr库和bottleneck库来加速某些类型的二进制数值和布尔运算。

这些库在处理大型数据集时特别有用,而且可以大大提高处理速度

看一个示例(使用100列×100,000行的DataFrame对象)

操作 优化后 优化前
df1>df2 13.32 125.35
df1*df2 21.71 36.63
df1+df2 22.04 36.50

这两个库是及其推荐安装的,可以使用pip或conda方式安装

安装后这两个都是默认启用的,可以通过设置以下选项来控制它们

pd.set_option('compute.use_bottleneck', False)
pd.set_option('compute.use_numexpr', False)

迭代

 Pandas对象的基本迭代行为取决于类型。

 对Series进行迭代时,它被看作是array-like,并且基本的迭代会产生值。

 DataFrame遵循类似dict的约定,即在对象的“键”生进行迭代

 简而言之,基本的迭代(for i in object)产生:

  • Series: 值
  • DataFrame:列标签

例如:在DataFrame对象上进行基本迭代会返回列的名字

df = pd.DataFrame({'col1': np.random.randn(3),
                    'col2': np.random.randn(3)}, index=['a', 'b', 'c'])

for col in df:
    print(col)

Pandas对象也可以使用items()方法对dict-like对象来迭代(key,value)

df = pd.DataFrame({'col1': np.random.randn(3),
                    'col2': np.random.randn(3)}, index=['a', 'b', 'c'])

for key_value in df.items():
    print(key_value)

要遍历DataFrame的行,也可以使用以下方法:

  • iterrows() : 以(index,Series)对的形式遍历DataFrame的行;这会将行转换为Series对象。
  • itertuples() : 将DataFrame的行作为值命名元组从而进行迭代。这比iterrows()要快得多。
for Series_row in df.iterrows():
    print(Series_row)
for tuples_row in df.itertuples():
    print(tuples_row)

排序

Pandas支持三种排序方式:按索引标签排序,按列值排序以及两者结合进行排序

按索引标签排序

Series.sort_index()DataFrame.sort_index() 方法用于对pandas对象根据标签排序

df = pd.DataFrame({
     'one': pd.Series(np.random.randn(3), index=['a', 'b', 'c']),
     'two': pd.Series(np.random.randn(4), index=['a', 'b', 'c', 'd']),
     'three': pd.Series(np.random.randn(3), index=['b', 'c', 'd'])})
#重新索引
unsorted_df = df.reindex(index=['a', 'd', 'c', 'b'],
                             columns=['three', 'two', 'one'])
print(unsorted_df)
unsorted_df.sort_index()
unsorted_df.sort_index(ascending=False)
unsorted_df.sort_index(axis=1)   #axis=1表示跨操作,这里根据列名进行排序(根据字母排序)

按值排序
df1 = pd.DataFrame({'one': [2, 1, 1, 1],
                     'two': [1, 3, 2, 4],
                     'three': [5, 4, 3, 2]})
#根据列标签'two'对应的值从小到大排序
df1.sort_values(by='two')
df1.sort_values(by=['one','two'])
按标签和值排序

作为by参数传递给DataFrame.sort_values()的字符串可以引用列或索引级别的名称。

#MultiIndex.from_tuples()生成一个元组类型的多重索引
idx = pd.MultiIndex.from_tuples([('a',1),('a',2),('a',2),('b', 2), ('b', 1), ('b', 1)]);
idx.names=['first','second']
idx   #多重索引,第一重名字为first,第二重名字为second
# np.arange(6,0,-1)  =>  array([6, 5, 4, 3, 2, 1])   
df_multi = pd.DataFrame({'A':np.arange(6,0,-1)},index=idx)
df_multi
df_multi.sort_values(by=['second','A'])    #'second'和'A'的顺序决定了先根据谁排序

IO工具(text,CSV,HDF5,...)

下面是一个包含可用读取器和写入器的表。

Type Data Description Reader Writer
text CSV read_csv to_csv
text Fixed-Width Text File read_fwf
text JSON read_json to_json
text HTML read_html to_html
text Local clipboard read_clipboard to_clipboard
MS Excel read_excel to_excel
binary OpenDocument read_excel
binary HDF5 Format read_hdf to_hdf
binary Feather Format read_feather to_feather
binary Parquet Format read_parquet to_parquet
binary ORC Format read_orc
binary Msgpack read_msgpack to_msgpack
binary Stata read_stata to_stata
binary SAS read_sas
binary SPSS read_spss
binary Python Pickle Format read_pickle to_pickle
SQL SQL read_sql to_sql
SQL Google BigQuery read_gbq to_gbq

更多关于IO详细解释与操作请到Pandas官网查阅

点此跳转


Merge, join, concatenate and compare

concatebate

concat()函数完成沿轴执行连接操作的所有繁重工作,同时在其他轴上执行索引(如果有的话)的可选集合逻辑(并集或交集)。

注意,之所以说“如果有”,是因为Series的串联轴只有一个可能的轴。

先看一个关于concat()函数的简单应用:

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                        'B': ['B0', 'B1', 'B2', 'B3'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']},
                       index=[0, 1, 2, 3])
    
df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
                        'B': ['B4', 'B5', 'B6', 'B7'],
                        'C': ['C4', 'C5', 'C6', 'C7'],
                        'D': ['D4', 'D5', 'D6', 'D7']},
                       index=[4, 5, 6, 7])
    

df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
                        'B': ['B8', 'B9', 'B10', 'B11'],
                        'C': ['C8', 'C9', 'C10', 'C11'],
                        'D': ['D8', 'D9', 'D10', 'D11']},
                       index=[8, 9, 10, 11])
    

frames = [df1, df2, df3]

result = pd.concat(frames)

concat()函数的参数介绍

pd.concat(objs,axis=0,join='outer',ignore_index=False,keys=None,levels=None,names=None,verify_integrity=False, copy=True)
  • objs:Series或DataFrame对象的序列或映射。如果传递了dict ,则除非传递了已排序的键,否则它将用作keys参数,在这种情况下,将选择值(请参见下文)。任何None对象将被无声地删除,除非它们都是None,在这种情况下,ValueError将被抛出。
  • axis :{0,1,…},默认值为0。要沿其连接的轴。
  • join:{'inner','outer'},默认为'outer'。如何处理其他轴上的索引。outer为联合,inner为交叉。
  • ignore_index:布尔值,默认为False。如果为True,则不要在串联轴上使用索引值。结果轴将标记为0,…,n-1。如果要串联对象时,串联轴没有有意义的索引信息,这将很有用。请注意,联接中仍会考虑其他轴上的索引值。
  • keys:序列,默认为无。使用传递的键作为最外层级别来构造层次结构索引。如果通过了多个级别,则应包含元组。
  • levels:序列列表,默认为无。用于构造MultiIndex的特定级别(唯一值)。否则,将从按键推断出它们。
  • names:列表,默认为无。生成的层次结构索引中的级别的名称。
  • verify_integrity:布尔值,默认为False。检查新的连接轴是否包含重复项。相对于实际数据连接而言,这可能会非常昂贵。
  • copy:布尔值,默认为True。如果为False,则不会不必要地复制数据。

回顾一下上面对参数讲解时的keys参数,假设我们想将特定的键与分割后的DataFrame片段,我们可以使用keys参数实现这一点:

result = pd.concat(frames, keys=['x', 'y', 'z'])

关于对Pandas对象的连接请关注官方文档

点此跳转


Merge

merge()作为DataFrame或命名为Series的对象之间所有标准数据库联接操作的入口点:

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
         left_index=False, right_index=False, sort=True,
         suffixes=('_x', '_y'), copy=True, indicator=False,
         validate=None)

参数详情如下:

  • left:一个DataFrame或命名为Series的对象。

  • right:另一个DataFrame或命名为Series的对象。

  • on:要连接的列或索引级的名称。必须在left和right中的DataFrame和/或Series对象中找到。如果没有通过,left_indexright_indexFalse,在DataFrames和/或Series列的交叉点会被推断为联接键。

  • left_on:左侧DataFrame或Series中的列或索引级别用作键。可以是列名称,索引级别名称,也可以是长度等于DataFrame或Series长度的数组。

  • right_on:右侧DataFrame或Series中的列或索引级别用作键。可以是列名称,索引级别名称,也可以是长度等于DataFrame或Series长度的数组。

  • left_index:如果为True,则使用左侧DataFrame或Series中的索引(行标签)作为其连接键。对于具有MultiIndex(分层结构)的DataFrame或Series,级别数必须与正确的DataFrame或Series中的联接键数匹配。

  • right_index:与left_index的DataFrame或Series的用法相同

  • how:其一'left''right''outer''inner'。默认为inner。有关每种方法的详细说明,请参见下文。

  • sort:按字典顺序按连接键对结果DataFrame进行排序。默认为True,设置为False可以在许多情况下显著提高性能。

  • suffixes:适用于重叠列的字符串后缀元组。默认为。('_x', '_y')

  • copy注意:始终True从传递的DataFrame或命名的Series对象复制数据(默认),即使不需要重新索引也是如此。在很多情况下都无法避免,但是可以提高性能/内存使用率。可以避免复制的情况有些病态,但是仍然提供了此选项。

  • indicator:将一列添加到输出DataFrame中_merge ,并在每一行的源上提供信息。_merge是类别类型的,left_only对于其合并键仅出现在'left'DataFrame或Series中right_only的观察值,对于其合并键仅出现在'right'DataFrame或Series中both的观察值以及在两个视图中均找到观察值的合并键,则取值为。

  • validate:字符串,默认为无。如果指定,则检查merge是否为指定的类型。

    • “ one_to_one”或“ 1:1”:检查合并键在左右数据集中是否唯一。

    • “ one_to_many”或“ 1:m”:检查合并键在左数据集中是否唯一。

    • “ many_to_one”或“ m:1”:检查合并键在右数据集中是否唯一。

    • “ many_to_many”或“ m:m”:允许,但不进行检查。


how选项中的合并方式

合并方式 SQL连接名称 描述
left LEFT OUTER JOIN 仅保留左边中的keys
right RIGHT OUTER JOIN 仅保留右边中的keys
outer FULL OUTER JOIN 使用两个对象中的keys的并集
inner INNER JOIN 使用两个对象中的keys的交集
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
                      'key2': ['K0', 'K1', 'K0', 'K1'],
                      'A': ['A0', 'A1', 'A2', 'A3'],
                      'B': ['B0', 'B1', 'B2', 'B3']})
 

right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
                      'key2': ['K0', 'K0', 'K0', 'K0'],
                       'C': ['C0', 'C1', 'C2', 'C3'],
                       'D': ['D0', 'D1', 'D2', 'D3']})
 

result = pd.merge(left, right, on=['key1', 'key2'])
result = pd.merge(left, right, how='left', on=['key1', 'key2'])
result = pd.merge(left, right, how='right', on=['key1', 'key2'])
result = pd.merge(left, right, how='outer', on=['key1', 'key2'])

result = pd.merge(left, right, how='inner', on=['key1', 'key2'])

Join

DataFrame.join()是将两个可能具有不同索引的数据文件的列组合成单个结果数据文件的一种方便方法。

这里有一个非常基本的例子:

left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
                      'B': ['B0', 'B1', 'B2']},
                     index=['K0', 'K1', 'K2'])
 
right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
                       'D': ['D0', 'D2', 'D3']},
                      index=['K0', 'K2', 'K3'])
 

result = left.join(right)
result = left.join(right, how='outer')  #并集
result = left.join(right, how='inner')  #交集

在列上的Join

left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                      'B': ['B0', 'B1', 'B2', 'B3'],
                      'key': ['K0', 'K1', 'K0', 'K1']})


right = pd.DataFrame({'C': ['C0', 'C1'],
                       'D': ['D0', 'D1']},
                      index=['K0', 'K1'])
 

result = left.join(right, on='key')

Compare

使用compare()compare()方法(两个compare()方法分别对应Series和DataFrame的compare方法),您可以分别比较两个DataFrame或Series,并总结它们之间的差异。

Pandas 的 V1.1.0版本中加入了此功能

如果显示AttributeError: 'DataFrame' object has no attribute 'compare' ,大概率是版本不够的原因

先定义一个DataFrame对象

df = pd.DataFrame(
     {
         "col1": ["a", "a", "b", "b", "a"],
         "col2": [1.0, 2.0, 3.0, np.nan, 5.0],
         "col3": [1.0, 2.0, 3.0, 4.0, 5.0]
     },
     columns=["col1", "col2", "col3"],
 )
df

df2复制df,并修改两个值

df2 = df.copy()
df2.loc[0,'col1'] = 'c'
df2.loc[2,'col3'] = 4.0
df2

比较

df.compare(df2)

如果需要,可选择差异在行上堆叠显示

df.compare(df2, align_axis=0)



文章翻译自官方文档
如果你发现文章中出现的错误或者任何疑问欢迎在下方评论区评论


利益相关
更多资源关注公众号“北方向北”(扫描右侧二维码也可关注)
点个大拇指支持支持,感谢

posted @ 2021-01-24 20:06  云北海  阅读(80)  评论(0编辑  收藏  举报