Python之pandas使用

欢迎关注

微信公众号:想进化的猿

头条号:python进阶者

 

一、pandas基本概念

        pandas是基于NumPy构建的一种数据处理工具,被誉为Python中的Excel,主要是为了解决数据分析任务而创建的。pandas中含有大量的数据处理运算相关库以及一些标准的数据模型,提供了高效操作大型数据集必备的工具。利用pandas提供的函数和方法能使我们快速便捷高效地处理数据。

二、pandas基本数据结构

        pandas主要包括三类数据结构:Series、DataFrame和Panel。

        Series:类似于NumPy中的一维ndarray,能保存不同种数据类型,包括字符串、boolean值、数字等。除了可以使用NumPy中一维ndarray可用的函数或方法外,还可以通过索引标签的方式获取数据,具有索引的自动对齐功能。

        DataFrame:二维的表格型数据结构。功能非常类似于R语言中的data.frame。从结构上来看,我们可以将DataFrame理解为Series的容器。

        Panel:三维数据结构。从结构上来看,我们可以理解为DataFrame的容器。

三、Series和DataFrame的基本创建

        Series和DataFrame是pandas中我们最常用的两个数据结构,我们分别来看一下它们的基本创建方法。(Series和DataFrame有多种创建方法,这里暂时先分别介绍建一个基本创建方法,等具体讲到两种数据结构时再详细介绍。)

创建Series

        Series可以通过NumPy的一维ndarray简单创建,基本用法如下。

import numpy as np
import pandas as pd

arr = np.arange(10)
print(arr)
print("---------------")

series = pd.Series(arr)
print(series)

        我们首先创建一个一维ndarray,然后通过pandas的Series()函数,传入一维ndarray。运行结果如下所示,可以看到,相比于NumPy的一维ndarray,Series多了一个默认从0开始的索引。

        如果我们想要修改Series的默认索引,只需要在使用Series()函数的时候多传一个index列表参数即可。需要注意的是,index的长度必须要与Series的长度保持一致。

import numpy as np
import pandas as pd

arr = np.arange(10)
print(arr)
print("---------------")

series = pd.Series(arr, index=list('abcdefghij'))
print(series)

        我们传入一个‘abcdefghij’的列表序列作为index,再次运行, Series的索引就改变了。运行结果如下所示。

创建DataFrame

        与Series类似,由于DataFrame相当于NumPy中二维ndarray的表格型数据结构,我们可以通过NumPy的二维ndarray来创建DataFrame,基本用法如下。

import numpy as np
import pandas as pd

arr = np.arange(12).reshape(3, 4)
print(arr)
print("---------------")

data_frame = pd.DataFrame(arr)
print(data_frame)

        通过pandas的DataFrame()函数,传入二维ndarray。运行结果如下所示,可以看到,相比于NumPy的二维ndarray,DataFrame的排列格式更像是一个Excel表格,行列都具有默认从0开始的索引。 

         同样的,我们可以修改DataFrame的默认行列索引,在使用DataFrame()函数的时候传入index列表参数修改行索引,传入columns列表参数修改列索引。其中,index和columns的长度分别必须与DataFrame的行长度和列长度保持一致。

import numpy as np
import pandas as pd

arr = np.arange(12).reshape(3, 4)
print(arr)
print("---------------")

data_frame = pd.DataFrame(arr, index=list('abc'), columns=list('ABCD'))
print(data_frame)

        我们将index设置为‘abc’的列表序列,columns设置为‘ABCD’的列表序列,再次运行,默认的行列索引都成功改变了。

 四、Series

        Series是带有标签的一维ndarray,可以存储任何数据类型的元素,其中,轴标签称为索引。

Series创建方法

        Series有多种创建方法,除了上述介绍的利用NumPy中的一维ndarray创建外,还可以通过标量、字典、pandas中的DataFrame创建,我们分别看一下这几种创建方法。

        1、通过NumPy中的一维ndarray创建

        此方法已在上述内容中有介绍,这里做个简单回顾,将一维ndarray传入pandas的Series()函数即可创建一个Series。

import numpy as np
import pandas as pd

arr = np.arange(10)
print(arr)
print("---------------")

series = pd.Series(arr, index=list('abcdefghij'))
print(series)

        index为可选参数,用于修改Series的默认索引。运行结果如下所示。

        2、通过标量创建Series

        当我们创建一组值都一样的Series时,可以直接通过标量创建,用法如下。

import numpy as np
import pandas as pd

series = pd.Series(10, index=['a', 'b', 'c'])
print(series)

        给pandas的Series()函数传入一个标量和一个索引列表index,标量就是生成的Series的所有元素值,index的大小决定了生成的Series的大小,若不设置index,默认Series大小为1。上述代码我们创建了一个大小为3,值为10的Series,运行结果如下所示。 

        3、通过字典创建Series

        Series的索引和值就类似于字典中的键值对,所以我们可以通过字典来创建Series,基本用法如下。

import numpy as np
import pandas as pd

dic = {'a': 1, 'b': 2, 'c': 3, 666: 4, True:5}
print(dic)
print("---------------")
series = pd.Series(dic)
print(series)

        向Series()函数传入一个字典,字典的key就是Series的索引,value就是Series的值。 运行结果如下所示。  

        4、从DataFrame中创建Series

        之前提到,pandas中Series与DataFrame的关系相当于NumPy中一维ndarray与二维ndarray的关系,因此,我们可以直接从DataFrame中获取Series。

import numpy as np
import pandas as pd

arr = np.arange(12).reshape(3, 4)
print(arr)
print("---------------")
data_frame = pd.DataFrame(arr, index=[1, 2, 3])
print(data_frame)
print("---------------")

series = data_frame[1]
print(series)

        我们首先创建一个DataFrame,然后使用索引即可获取一个Series。运行结果如下所示,可以看到,通过对DataFrame直接索引获取的是列的值,其实也可以通过loc和iloc方法获取行的值,只是获取行的值得到的依然是DataFrame,这里暂时不做展开,等详细介绍DataFrame的时候再介绍。

Series索引与切片

        1、下标索引

        下标索引与一维ndarray一样,只需根据序列获取所在位置上的值即可。我们创建一个Series,然后获取第7个位置上(从0开始计)的值。这里需要特别注意的是,Series的下标索引不支持通过-1来获取最后一个位置上的值。

import numpy as np
import pandas as pd

arr = np.random.rand(10)
series = pd.Series(arr, index=list('abcdefghij'))
print(series)
print("---------------")

print(series[6])
print(type(series[6]))
print(series[6].dtype)

        运行结果如下所示。我们打印了获取的值的数据类型,可以看到,Series存储浮点型数据时自动保留了小数点后六位。事实上,pandas对浮点型数据的存储都会自动保留一定的小数位数,不同版本的pandas自动保留的位数可能会有出入。

        2、标签索引

        Series的标签特性使它也可以通过标签进行索引,用法就类似于字典,传入标签索引即可获取对应的值。 

import numpy as np
import pandas as pd

arr = np.random.rand(10)
series = pd.Series(arr, index=list('abcdefghij'))
print(series)
print("---------------")

print(series[6])
print(series['g'])

        运行结果如下所示,通过下标索引和标签索引都能获取到对应的值。

        3、切片索引

        Series的切片索引与ndarray中的切片索引用法基本一致,区别在于Series的切片索引除了使用下标外还可以对标签进行切片。另外,虽然Series的下标索引不能使用-1,但是在切片中是可以使用-1来表示最后一个位置的。

import numpy as np
import pandas as pd

arr = np.random.rand(5)
series = pd.Series(arr2, index=list('edcba'))
print(series)
print("---------------")
print(series[1:3])
print("---------------")
print(series['d':'b']) # 包含末端
print("---------------")
print(series[:-1])

        通过对下标切片或对标签切片都可以进行切片索引,但是需要注意两者间的区别,对下标切片索引时,是包头去尾的,即包括小的,不包括大的,而对标签切片索引时,是包含末端的。运行结果如下所示。

        4、布尔型索引

        Series的布尔型索引与NumPy中布尔型索引的功能一样,会取出满足条件的值组成一个新的Series。基本用法如下。

import numpy as np
import pandas as pd

arr = np.random.rand(5)
series = pd.Series(arr)
print(series)
print("---------------")

bool = series > 0.5
print(bool)
print("---------------")
print(series[bool])

         运行结果如下所示。

Series常用功能

        1、通过head()和tail()查看Series数据

        当Series数据较多,且我们只需要查看前几个或后几个元素时,打印整个Series就会显得特别臃肿,这时我们可以使用head()函数和tail()函数分别查看前几个元素和最后几个元素。基本用法如下。

import numpy as np
import pandas as pd

arr = np.random.rand(100)
series = pd.Series(arr)
# 默认为5
print(series.head())
print("---------------")
print(series.head(2))
print("---------------")
print(series.tail())
print("---------------")
print(series.tail(3))

        head()函数和tail()函数默认会取5个元素,当想查看指定个数的元素时,只需要将个数值传入即可。运行结果如下所示。

        2、使用reindex()函数重新索引

        这里的重新索引并不是重新设置索引,而是从源Series中获取索引所对应的数据,若源Series中没有相关索引,会使用缺失值NaN填充,我们看一下效果。

import numpy as np
import pandas as pd

arr = np.random.rand(5)

series1 = pd.Series(arr, index=list('abcde'))
print(series1)
print("---------------")

# 根据索引取值,若无对应值默认会有缺失值NaN
series2 = series1.reindex(list('bcdef'))
print(series1)
print("---------------")
print(series2)

        上述代码我们创建了一个索引为“abcde”的Series,然后通过reindex()函数重新索引为“bcdef”,reindex()函数只是生成一个新的Series,并不改变源Series。运行结果如下所示,我们可以看到, 对于源Series(series1)中有的索引“bcde”,新生成的Series(series2)会将数据取出来,而对于series1中没有的索引“e”,series2会以缺失值NaN填充。

        有时我们不想让缺失值NaN出现,可以传入fill_value参数给缺失的索引设置一个默认填充值。

import numpy as np
import pandas as pd

arr = np.random.rand(5)

series1 = pd.Series(arr, index=list('abcde'))
print(series1)
print("---------------")

# 根据索引取值,若无对应值默认会有缺失值NaN
series2 = series1.reindex(list('bcdef'), fill_value=0)
print(series2)

        运行后可以发现, 在缺失的索引位置上,值变成了我们设置的默认填充值。

        3、Series的自动对齐特性

        当多个Series进行运算时,Series会根据索引值自动对齐,对共有的索引对应值进行相关运算,不共有的索引对应值则分别以缺失值NaN填充。

import numpy as np
import pandas as pd

series1 = pd.Series(np.random.rand(3), index=list('abc'))
print(series1)
print("---------------")
series2 = pd.Series(np.random.rand(4), index=list('bcde'))
print(series2)
print("---------------")
print(series1 + series2)

        运行结果如下。对于共有索引“bc”,对应值会进行相加,而对于非共有索引“ade”,对应的值为NaN。 

        对于缺失值的处理这里暂时不做展开,后面会单独详细介绍。

        4、Series删除元素函数drop()

        pandas中,我们使用drop()函数来删除Series中的元素,传入要删除的索引标签或索引标签序列可以删除一个或多个元素。

import numpy as np
import pandas as pd

series = pd.Series(np.random.rand(5), index=list('abcde'))
print(series)
print("---------------")
series1 = series.drop(labels='a')
series2 = series.drop(labels=['b', 'c'])
print(series)
print("---------------")
print(series1)
print("---------------")
print(series2)

        上述代码中drop()函数传入的参数也可以是index='a',index=['b', 'c'],运行结果如下所示。 需要特别注意的是,Series不支持传下标来进行删除元素,上述代码中若使用drop(index=0)就会报错,无法成功删除第一个元素。

        与reindex()函数一样,drop()函数也只是生成新的Series,而不会改变源Series。但有时我们就是想删除源Series的元素,这个时候可以设置参数inplace,该参数默认情况下为False,即不改变源Series,当我们将inplace设置成True时,源Series就改变了,但请注意,此时它将不再生成新Series。

import numpy as np
import pandas as pd

series = pd.Series(np.random.rand(5), index=list('abcde'))
print(series)
print("---------------")
series2 = series.drop('a', inplace=True)
print(series2)
print("---------------")
print(series)

        运行结果如下所示。可以看到,当设置inplace=True时,源Series成功得到了改变,但用于接收的series2为None,可见没有生成新的Series。

        除此之外,pandas中还有用于删除空值或缺失值的dropna()函数和用于删除重复值的drop_duplicates()函数,用法如下。

import numpy as np
import pandas as pd

arr = np.array([1, 2, 1, 3, None, 2, 4, 5, None, 1, 2, 3])
series = pd.Series(arr)
print(series)
print("---------------")

series.dropna(inplace=True)
print(series)
print("---------------")

series.drop_duplicates(inplace=True)
print(series)

        我们创建一个既有重复值又有空值的Series,然后分别使用dropna()函数和drop_duplicates()函数分别删除空值和重复值,为了便于比较,我们设置inplace=True,直接在源Series上修改。运行结果如下所示。

5、Series添加元素 

        给Series添加元素可以通过直接添加元素和使用append()函数连接Series的方式,基本使用方法如下。

import numpy as np
import pandas as pd

series1 = pd.Series(np.random.rand(5))
series2 = pd.Series(np.random.rand(5), index=list('abcde'))
print(series1)
print("---------------")
print(series2)
print("---------------")
series1[5] = 1 
series2['f'] = 2
series2[5] = 2

series1 = pd.Series(np.array([1, 2, 3, 4, 5]), index=list('abcde'))
series2 = pd.Series(np.array([2, 3, 4, 5, 6]), index=list('bcdef'))
print(series1)
print("---------------")
print(series2)
print("---------------")
series3 = series1.append(series2)
print(series3)

        不同于drop()函数无法使用下标索引,添加元素除了使用标签索引外,使用下标索引的方式也是可以直接给Series添加对应元素的。append()函数连接两个Series,生成的新Series将忽视标签的重复,包含源Series中的所有元素。运行结果如下所示。

6、Series元素排序

        pandas中可以使用sort_index()函数或sort_values()函数分别对Series的索引及元素值进行排序,ascending参数用于设置正序或倒序,默认为True正序,设置ascending为False时倒序排序。

import numpy as np
import pandas as pd

series = pd.Series(np.random.randn(5), index=list('bdeac'))
print(series)
print("---------------")

print(series.sort_index())
print("---------------")
print(series.sort_index(ascending=False))
print("---------------")
print(series.sort_values())
print("---------------")
series.sort_values(ascending=False, inplace=True)
print(series)

        运行结果如下所示。同样地,sort_index()函数和sort_values()函数只是生成新的Series,而不影响源Series,要修改源Series,需要设置inplace=True。

五、DataFrame

        DataFrame是一个表格型的数据结构,包含一组有序的列,它的值类型可以是数值、字符串、布尔型等各种数据类型。DataFrame中的数据以一个或多个二维块存储,但它不是列表、字典或一维数组结构。

DataFrame创建方法

        1、通过二维ndarray创建DataFrame

        DataFrame在结构上类似于NumPy中的二维ndarray,因此我们可以通过二维ndarray来创建DataFrame,基本用法如下。

import numpy as np
import pandas as pd

arr = np.random.rand(12).reshape(3, 4)
print(arr)
print("---------------")
df1 = pd.DataFrame(arr)
df2 = pd.DataFrame(arr, index=list('abc'), columns=list('ABCD'))
print(df1)
print("---------------")
print(df2)

        首先,创建一个二维ndarray,然后使用pandas的DataFrame函数,将该ndarray传入即可。该方法创建一个与传入的ndarray相同形状的DataFrame,我们可以显示地指定DataFrame的行索引(index)和列索引(columns),若不指定index和columns,则行索引和列索引均返回默认的数字标签格式。运行结果如下所示。

        我们可以利用type()函数看一下DataFrame的行标签、列标签以及值的数据类型。

import numpy as np
import pandas as pd

arr = np.random.rand(12).reshape(3, 4)
frame = pd.DataFrame(arr, index=list('abc'), columns=list('ABCD'))
print(frame)
print("---------------")
print(frame.index) # 行标签
print(type(frame.index))
print("---------------")
print(frame.columns) # 列标签
print(type(frame.columns))
print("---------------")
print(frame.values) # 值
print(type(frame.values))

        运行结果如下所示。可以看到,无论是行标签index,还是列标签columns,都属于索引标签类Index。而DataFrame的值values,跟我们想的一样,它是一个NumPy的ndarray,事实上, DataFrame只是给二维ndarray添加了行标签和列标签。

        2、通过数组字典创建DataFrame

        给pandas的DataFrame()函数传入一个数组字典也可以创建DataFrame,其中字典的key将会作为生成的DataFrame的列标签columns,行标签index默认为数字标签。可以对行标签index进行修改,但是长度必须要一致。

import numpy as np
import pandas as pd

# 列长度需要保持一致
data1 = {'a': [11, 12, 13],
         'b': [21, 22, 23],
         'c': [31, 32, 33]}
data2 = {'a': np.random.rand(3),
         'b': np.random.rand(3)} # 3改为4列长度不一会报错
print(data1)
print("---------------")
print(data2)
print("---------------")
d1 = pd.DataFrame(data1, index=list('ABC'))
d2 = pd.DataFrame(data2)
print(d1)
print("---------------")
print(d2)

        需要注意的是,使用数组字典创建DataFrame时,列长度必须保持一致,否则会报错,无法生成DataFrame。运行结果如下所示。 

        使用数组字典创建DataFrame时,若在DataFrame()函数中传入columns,作用并不是重新设置列索引,而是重新指定列的顺序。如果现有数据中无该列,则会生成缺失值NaN来填充,此时传入的columns是可以少于原数据的列数量的。我们给上述代码中data1创建时的DataFrame()函数传入一个columns,代码如下。

import numpy as np
import pandas as pd

data = {'a': [11, 12, 13],
         'b': [21, 22, 23],
         'c': [31, 32, 33]}
print(pd.DataFrame(data, index=list('ABC')))
print("---------------")
d = pd.DataFrame(data, index=list('ABC'), columns=list('bd'))
print(d)

        运行结果如下所示,我们将列索引设置为b、d,对于原数据的列中包含的索引b,新DataFrame会将该列的值取下来,而对于不包含的新索引d,新DataFrame会使用缺失值NaN填充该列。

        3、通过Series字典创建DataFrame

        由Series组成的字典与数组字典类似,在用Series字典创建DataFrame时,只需在DataFrame()函数中传入一个Series字典即可,字典的key作为生成的DataFrame的列标签columns,行标签index默认为数字标签。与数组字典创建DataFrame不同的是,使用Series字典创建DataFrame时,Series的长度是可以不一样的,新生成的DataFrame会自动使用缺失值NaN进行填充。基本使用方法如下。

import numpy as np
import pandas as pd

# 列长度可以不一致
data1 = {'a': pd.Series(np.random.rand(2)),
         'b': pd.Series(np.random.rand(3))}
data2 = {'a': pd.Series(np.random.rand(2), index=list('AB')),
         'b': pd.Series(np.random.rand(3), index=list('ABC'))} 
d1 = pd.DataFrame(data1)
d2 = pd.DataFrame(data2)
print(d1)
print("---------------")
print(d2)

        运行结果如下所示。

        4、 通过嵌套字典创建DataFrame

        在DataFrame()函数中传入一个嵌套字典也可以创建DataFrame,父字典的key就是生成的DataFrame的列标签columns,子字典的key则作为生成的DataFrame的行标签index。在使用DataFrame()函数时,使用columns参数可以增加和减少序列,空值用NaN填充,但是我们不能改变原有index。

import numpy as np
import pandas as pd

data = {'aa': {'a1': 1, 'a2': 2, 'a3': 3},
        'bb': {'b1': 1, 'b2': 2, 'b3': 3},
        'cc': {'c1': 1, 'c2': 2}}
print(data)
print("---------------")
df1 = pd.DataFrame(data)
print(df1)
print("---------------")
df2 = pd.DataFrame(data, columns=['aa', 'dd'])
print(df2)

        在使用columns参数时,DataFrame会自动舍弃该列空值。上述代码中,我们设置列索引columns为bb、dd,对于原列索引中有的索引bb,新DataFrame会取该列值,但是舍弃了为空值的b1、b2、b3、c1、c2行,然后对于未包含在原列索引中的索引dd,直接用NaN填充。运行结果如下所示。

        5、通过字典列表创建DataFrame

        通过字典列表创建DataFrame即向DataFrame()函数传入一个字典列表,字典的key即为生成的DataFrame的列标签columns,不同字典间的不同key将合并组成生成的DataFrame的列。对于列表中的字典,如果有相同的key,则会生成不同的行,行标签index默认为数字索引。如果列表中的每个字典间都没有相同key存在,那么将生成一个单行的DataFrame。

import numpy as np
import pandas as pd

data1 = [{'a': 1, 'b': 2}, {'a': 3, 'd':4, 'e': 5}]
data2 = [{'a': 1, &
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值