Pandas
Pandas库基于Numpy库,提供了很多用于数据操作与分析的功能。
安装与使用
安装:
pip install pandas
根据惯例,我们使用如下的方式引入pandas:
import pandas as pd
两个常用数据类型
pandas提供两个常用的数据类型:
- Series
- DataFrame
Series类型
Series类型类似于Numpy的一维数组对象,可以将该类型看做是一组数据与数据相关的标签(索引)联合而构成(带有标签的一维数组对象)。
创建方式
Series常用的创建(初始化)方式:
- 列表等可迭代对象
- ndarray数组对象
- 字典对象
- 标量
# 通过列表(等可迭代对象)创建。
p = pd.Series([5, 8, 10, 90])
p = pd.Series((1, 2, 3, 4))
# p = pd.Series(range(20))
# 通过ndarray数组来创建Series。
# p = pd.Series(np.array([53, 32, 99, 12]))
# 通过字典对象创建Series。字典的key作为Series的索引。字典的value作为元素的值。
# p = pd.Series({"a": 100, "b": 200, "c":400})
# p = pd.Series(10)
# print(p)
# 当我们没有显式指定索引,会自动生成(创建)从0开始,依次增1的索引。(0, 1, 2, 3 ……)
p = pd.Series([1, 20, 30, -15])
# 我们也可以在创建Series的同时,通过index参数指定索引。
p = pd.Series([1, 20, 30, -15], index=["a", "b", "c", "d"])
# 我们也可以在创建Series对象之后,去修改(设置)对象的索引。
# p.index = [9, 8, 7, 6]
# p = pd.Series(10, index=[5, 6, 7, 8])
# print(p)
相关属性
- index
- values
- shape
- size
- dtype
Series对象可以通过index与values访问索引与值。其中,我们也可以通过修改index属性来修改Series的索引。
说明:
- 如果没有指定索引,则会自动生成从0开始的整数值索引,也可以使用index显式指定索引。
- Series对象与index具有name属性。Series的name属性可在创建时通过name参数指定。
- 当数值较多时,可以通过head与tail访问前 / 后N个数据。【中间的怎么办?】
- Series对象的数据只能是一维数组类型。
Series也可以通过索引进行访问数据,与Numpy的ndarray数组对象索引是否存在不同?
# index 返回Series对象的索引对象
p = pd.Series([1, 2, 3 , 4], index=list("abcd"))
# p.index
# values 返回Series所关联的值。
# Series可以看做类似字典的结构,index返回字典的key,values返回字典的value。
# values为ndarray数组类型。(一维数组类型。)
# p.values
# shape 返回Series的形状。
# print(p.shape)
# print(p.values.shape)
# size 返回元素的个数
# print(p.size)
# dtype 返回元素的类型
# print(p.dtype)
# Series对象与Series的索引对象(index属性返回的对象),二者都具有name属性,用来指定名字。
# 我们可以在创建Series对象时,通过name属性指定Series对象的名称。
p = pd.Series(["a", "c", "k", "xyz"], index=[9, 10, 20, 15], name="Series的名字")
# 我们也可以在创建Series对象之后,通过name属性来设置Series的名称。
p.name = "如果在创建时忘了,可以在稍后进行赋值。"
# 为Series的index属性来设置名称。
# p.index.name = "Index的名称。"
# 创建索引对象
# Series的name与Series.index的name可以在输出Series对象时,得到体现。但是,
# 二者的name属性,作用可不只是体现在输出中。
# ind = pd.Index(["a", "b", "c"], name="Seires索引(index)的name值")
# p = pd.Series([1, 2, 3], index=ind)
# p2 = pd.Series([1, 2, 3], index=ind)
# p3 = pd.Series([1, 2, 3], index=ind)
p = pd.Series(range(300))
# 如果数量量较大,我们可以使用head与tail方法,访问前(后)n条数据。
# print(p)
# p.head(10)
# p.tail(5)
# 当我们不指定参数时,默认值为5。
# p.head()
# Series仅支持一维的数据。
# p = pd.Series([[1, 2], [3, 4]])
# 会出现错误。
# p = pd.Series(np.array([[1, 2],[3, 4]]))
# p
# ndarray的索引与Series的索引是不相同的。
# 对于ndarray而言,索引(类似与列表list)就是每个元素的位置(序号),我们是不能自定义改变的。
# 对于Series而言,索引为类似字典(dict)中的key(映射),我们是可以自定义改变的。
array = np.array([1, 2, 3])
print(array[2])
s = pd.Series([1, 2, 3])
print(s[2])
print(array[-1])
# 错误
# print(s[-1])
Series相关操作
Series在操作上,与Numpy数据具有如下的相似性:
- 支持广播与矢量化运算。
- 支持索引与切片。
- 支持整数数组与布尔数组提取元素。
运算
Series类型也支持矢量化运算与广播操作。计算规则与Numpy数组的规则相同。同时,Numpy的一些函数,也适用于Series类型,例如,np.mean,np.sum等。
多个Series运算时,会根据索引进行对齐。当索引无法匹配时,结果值为NaN(缺失值)。
说明:
- 我们可以通过pandas或Series的isnull与notnull来判断数据是否缺失。
- 除了运算符以外,我们也可以使用Series对象提供的相关方法进行运算【可以指定缺失的填充值】。
- 尽管Numpy的一些函数,也适用于Series类型,但Series与ndarray数组对于空值NaN的计算处理方式上是不同的。【Numpy的计算,会得到NaN,而Series会忽略NaN】
s1 = pd.Series([1, 2, 3])
# 广播运算
s1 + 100
s2 = pd.Series([4, 5, 6])
# 矢量化运算。
s1 + s2
# np.sum,np.mean等函数,也支持Series类型。
# print(np.sum(s1))
# 注意,在矢量化计算上,Series与ndarray的对齐方式是不同的。
# 对于ndarray,就是进行对位运算。而Series会根据索引进行对齐运算。无法匹配的,会产生空值(NaN)。
s1 = pd.Series([1, 2, 3], index=[0, 1, 2])
s2 = pd.Series([2, 3, 4], index=[1, 2, 3])
# s3 = s1 + s2
# print(s3)
# print(s3.isnull())
# isnull视NaN与None为空值。用来判断是否为空值,是返回True,否则返回False。
s = pd.Series([1, 2, float("NaN"), np.NAN, None])
# s.isnull()
# notnull与isnull相反,用来判断是否不是空值。不是空值返回True,否则返回False。
# s.notnull()
# s1 + s2
# 除了使用运算符之外,我们也可以使用Series对象的计算函数,来进行运算。
# 可以使用fill_value来指定,当产生空值后,使用什么值进行填充。
# s1.add(s2, fill_value=500)
# 尽管np.sum,np.mean支持Series,但是,Series类型与ndarray数组类型,运行的行为
# 有些不同。对于NaN(空值),ndarray数组会返回Nan,而Series不会(会忽略空值)。
a = np.array([1, 2, 3, np.nan])
# np.sum(a)
s = pd.Series([1, 2, 3, np.nan])
np.sum(s)
索引
标签索引与位置索引
如果Series对象的index值为非数值类型,通过[索引]访问元素,索引既可以是标签索引,也可以是位置索引。这会在一定程度上造成混淆。我们可以通过:
- loc 仅通过标签索引访问。
- iloc 仅通过位置索引访问。
这样,就可以更加具有针对性去访问元素。
整数数组索引与布尔数组索引
Series也支持使用整数数组与布尔数组进行索引。与Numpy数组相同,二者返回的是原数组数据的拷贝(复制)。
说明:
- 与ndarray数组的整数索引不太相同,Series的整数数组索引,既可以是标签数组索引,也可以是位置数组索引。
# s = pd.Series([10, 20, 30], index=["a", "b","c"])
# 标签索引
# s["a"]
# 位置索引
# s[1]
# 当标签索引是数值类型时,位置索引失效。
# s = pd.Series([10, 20, 30], index=[2, 3, 4])
# s[2]
# s[0]
# 因为通过Series[索引]的方式访问元素,既支持标签索引,也支持位置索引(如果标签是数值类型,则位置索引失效)。
# 因此,非常容易造成混淆。建议不要这样访问。
# 建议使用.iloc与loc的方式访问。
# .iloc专门通过位置索引访问。
# .loc专门通过标签索引访问。
# s = pd.Series([10, 20, 30], index=["a", "b","c"])
# s.iloc[2]
# 错误,iloc不支持标签索引。
# s.iloc["a"]
# s.loc["a"]
# 错误,loc不支持位置索引。
# s.loc[0]
切片
Series也支持切片访问一个区间的元素。与Numpy的数组相同,切片返回的是原数组数据的视图。
Series的切片与Numpy的ndarray数组对象切片是否存在不同?
s = pd.Series([5, 8, 10, 39, 3, 83], index=list("abcdef"))
# 切片返回的是原数组的视图。
# x = s.iloc[2 : 5]
# x.iloc[0] = 3000000
# print(x)
# print(s)
# 切片,可以分为两种:
# 1位置索引切片
# 2标签索引切片
# Series既可以通过位置索引切片,也可以通过标签索引切片。
# 当通过位置索引切片时,包含起始点,不包含终止点。
# 当通过标签索引切片时,包含起始点,也包含终止点。
x = s.loc["a":"e"]
x
Series的CRUD
Series索引-数值CRUD操作:
- 获取值
- 修改值
- 增加索引-值
- 删除索引-值
s = pd.Series([1, 2, 3, 4], index=["a", "b", "c", "d"])
# 不建议使用
print(s[0])
# print(s.ix[0])
# print(s.ix["a"])
# 建议的访问方式
print(s.iloc[0])
print(s.loc["a"])
# 修改值
s.iloc[0] = 1000
# 增加索引值
s["e"] = 11111
# print(s)
# 删除键值对(字典的方式)
# del s["e"]
# 删除键值对(Series的方式)
# s = s.drop("e")
# 就地修改
# inplace指定是否要进行就地修改。默认为False(返回一个新的对象)
# 当指定inplace=True时,会影响到方法的返回值。
# 如果inplace值为False(默认),不会修改现有的Series对象,而是返回一个新创建的对象。
# 新创建的对象为现有Series对象修改之后的结果。
# 如果inplace值为True,会对现有Series对象进行就地修改,不会创建新的对象,方法返回值为None。
# print(s.drop("e", inplace=True))
# drop方法也可以删除多个值。
s.drop(["e", "a", "c"], inplace=True)
print(s)
部分内容参考光环笔记!希望对大家有所帮助