赞
踩
Pandas是用于数据操纵和分析,建立在Numpy之上的。Pandas为Python带来了两种新的数据结构:Pandas Series和Pandas DataFrame,借助这两种数据结构,我们能够轻松直观地处理带标签数据和关系数据。
Pandas功能:
允许为行和列设定标签
可以针对时间序列数据计算滚动统计学指标
轻松处理NaN值
能够将不同的数据集合并在一起
与Numpy和Matplotlib集成
Pandas series 是像数组一样的一维对象,可以存储很多类型的数据。Pandas series 和 Numpy array之间的主要区别之一是你可以为Pandas series 中的每个元素分配索引标签;另一个区别是Pandas series 可以同时存储不同类型的数据。
Series对象实际上都由两个数组组成,具有 index和 values两大属性。
index:保存标签信息,是从 NumPy数组继承的 Index对象;
values:保存值,是一维 NumPy数组对象。
1、同时指定index属性和value属性的具体值
2、仅制定values属性的值。如果只制定 values的取值,没有设定 index属性的取值,则会默认产生从0开始,步长为1,长度为 values
pd.Series(data, index)
groceries = pd.Series(data=[30, 6, 'yes', 'No'], index=['eggs', 'apples', 'milk', 'bread']) ser = pd.Series(data=[[0, 1, 2, 3], [1, 3, 5, 7], [2, 4, 6, 8]], index=(['a', 'b', 'c']))
注意:
1、 如果参数中只提供index值,未提供data,则会生成value全部为nan的空索引
2、 如果参数中只提供了data值,未提供index索引,则会生成index从0开始按顺序的数字索引
其它各种创建索引代码:
s1=pd.Series(np.random.randn(5))
s2=pd.Series([0,np.NaN,2,4,6,8,True, 10, 12])
s3=pd.Series({'a': 1,'b': 3,'c': 5,'d': 7})
s4=pd.Series([1,3,5,7,9], index=['a','b','c','d','e'])
查看 Pandas Series 属性
# Pandas Series 元素数量
print(groceries.size)
# Pandas Series 形状
print(groceries.shape)
# Pandas Series 维度
print(groceries.ndim)
# Pandas Series 索引列表
print(groceries.index)
# Pandas Series 元素列表
print(groceries.values)
查看是否存在某个索引标签:in
print('book' in groceries)
Pandas Series 提供了两个属性 .loc 和 .iloc
.loc 表明我们使用的是标签索引访问
.iloc 表明我们使用的是数字索引访问
# 标签索引
print(groceries['eggs'])
print(groceries[['eggs', 'milk']])
# 数字索引
print(groceries[1])
print(groceries[[1, 2]])
print(groceries[-1])
# 明确标签索引
print(groceries.loc['milk'])
print(groceries.loc[['eggs', 'apples']])
# 明确数字索引
print(groceries.iloc[0])
print(groceries.iloc[[0, 1]])
另外还有get函数,是专门根据索引获取值的:
Pandas Series.get()函数从给定键(DataFrame列,Panel slice等)的对象中获取项目。如果未找到,则返回默认值None;
返回值:
如果是单个key值查找,直接返回对应的值
如果是多个key同时查找,返回的是一个子Series对象
示例代码:
a = "I don't know how they've gotten away with all of that".split()
b = [91, 18, 27, 36, 15, 24, 33, 72, 31, 10, 56]
c = pd.Series(b, index = a)
print(c.get('all'))
print(c.get(['all','of']))
输出:
31
all 31
of 10
直接标签访问,值修改就可
groceries['eggs'] = 2
print(groceries)
删除:drop(参数 1:lable,标签;参数 2:inplace=True/False,是/否修改原 Series)
print(ser.drop(['b']))
print(ser.drop(['a', 'b'], inplace=True))
Pandas Series执行元素级算术运算:加、减、乘、除
fruits = pd.Series(data=[10, 6, 3], index=['apples', 'oranges', 'bananas'])
# 所有数字进行运算
print(fruits + 2)
print(fruits - 2)
print(fruits * 2)
print(fruits / 2)
# 所有元素应用Numpy中的数学函数
print(np.exp(fruits))
print(np.sqrt(fruits))
print(np.power(fruits, 2))
# 部分元素进行运算
print(fruits[0] - 2)
print(fruits['apples'] + 2)
print(fruits.loc['oranges'] * 2)
print(np.power(fruits.iloc[0], 2))
时间序列类型也是一种 Series类型,与一般 Series对象不同的是,时间序列的 index属性取值为时间戳。
示例代码:
import pandas as pd
import numpy as np
#利用pandas生成日期数组作为索引,作为参数两边都会包含
date_idx=pd.date_range('2021/1/1','2021/12/31')
#新建时间序列索引
s=pd.Series(np.random.rand(len(date_idx)),index=date_idx)
#获取1到3月份的数据,注意切片时两头都会包含,和其它的切片不太一样
print(s['2021/1':'2021/3'])
说明:
1、时间序列的创建:方式与一般的 Series对象创建方式相同,我们只需要将 index设置为Timestamp对象。使用 to datetime()来将 Series的 index属性转换为 Datetimelndex:
2、截取时间段数据:一般的索引操作对时间序列依然有效,其特别之处在于对时间序列索引的操作优化。对于较长的序列,还可以只传入年份或年份加月份来选取切片:
3、滞后或超前操作
滞后操作指的是将t期的数据换成t一a期的数据,而超前操作自然是将t期的数据换成t+a期的数据。对于滞后或者超前操作,可以使用shift()方法。
1、按索引进行排序
#定义一个Series
s = Series([1,2,3],index=["a","c","b"])
#对Series的索引进行排序,默认是升序
print(s.sort_index())
'''
a 1
b 3
c 2
'''
#对索引进行降序排序
print(s.sort_index(ascending=False))
'''
c 2
b 3
a 1
'''
2、按值进行排序
s = Series([np.nan,1,7,2,0],index=["a","c","e","b","d"])
#对Series的值进行排序,默认是按值的升序进行排序的
print(s.sort_values())
'''
d 0.0
c 1.0
b 2.0
e 7.0
a NaN
'''
#对Seires的值进行降序排序
print(s.sort_values(ascending=False))
'''
e 7.0
b 2.0
c 1.0
d 0.0
a NaN
'''
对值进行排序的时候,无论是升序还是降序,缺失值(NaN)都会排在最后面。
排名和排序有点类似,排名会有一个排名值(从1开始,一直到数组中有效数据的数量),它与numpy.argsort的间接排序索引差不多,只不过它可以根据某种规则破坏平级关系。
s = Series([1,3,2,1,6],index=["a","c","d","b","e"])
#默认是根据值的大小进行平均排名
'''
1是最小的,所以第一个1排在第一,第二个1排在第二
因为取的是平均排名,所以1的排名为1.5
'''
print(s.rank())
'''
a 1.5
c 4.0
d 3.0
b 1.5
e 5.0
'''
#根据值在数组中出现的顺序进行排名
print(s.rank(method="first"))
'''
a 1.0
c 4.0
d 3.0
b 2.0
e 5.0
'''
method参数除了,first按值在原始数据中的出现顺序分配排名,还有min使用整个分组的最小排名,max是用整个分组的最大排名,average使用平均排名,也是默认的排名方式。还可以设置ascending参数,设置降序还是升序排序。
Pandas DataFrame 是具有带标签的行和列的二维数据结构,可以存储多种类型的数据,类似于电子表格。
Dataframe:一个表格型的数据结构每一列代表一个变量,而每一行则是一条记录。简单地说,DataFrame是共享同一个 index的Series的集合。
在创建 DataFrame对象之前,要先创建一个索引。索引是一个 DataFrame对象必须有的元素,起到标识的作用。
1、手动创建数据
2、从其他地方读取数据:read_table()函数、读取csv文件数据、读取MySQL数据。
第一步:创建 Pandas Series 字典
第二步:将字典传递给 pd.DataFrame
items = {'Bob': pd.Series(data=[245, 25, 55], index=['bike', 'pants', 'watch']),
'Alice': pd.Series(data=[40, 110, 500, 45], index=['book', 'glasses', 'bike', 'pants'])}
shopping_carts = pd.DataFrame(items)
print(shopping_carts)
通过关键字 columns 和 index 选择要将哪些数据放入 DataFrame 中
shopping_cart = pd.DataFrame(items, index=['bike', 'pants'], columns=['Bob'])
print(shopping_cart)
访问整列:dataframe[['column1', 'column2']]
# 读取列
print(shopping_carts[['Bob', 'Alice']])
访问整行:dataframe.loc[['row1', 'row2']]
# 读取行
print(shopping_carts.loc[['bike']])
访问某行某列:dataframe['column']['row'],先提供行标签,将出错。
# 读取某一列某一行
print(shopping_carts['Bob']['bike'])
take函数
Pandas dataframe.take()函数沿轴返回给定位置索引中的元素。这意味着我们没有根据对象的index属性中的实际值建立索引。我们正在根据元素在对象中的实际位置建立索引。
示例:
dataframe.take([2,4,0])
取第 3、5、1 三个值,如果按索引从0开始,则是2,4,0
添加整列(末尾添加列),空值用 None
# 添加列
shopping_carts['Mike'] = [10, 30, 10, 90, None]
添加整行(末尾添加行),把新添加行创建为 dataframe,通过 append() 添加
# 添加行
new_items = [{'Alice': 30, 'Bob': 20, 'Mark': 35, 'Mike': 50}]
new_store = pd.DataFrame(new_items, index=['store3'])
shopping_carts = shopping_carts.append(new_store)
只能删除整列:pop('lable')
# 删除整列
shopping_carts.pop('Jey')
删除行或者列:drop(['lable1', 'lable2'], axis=0/1) 0表示行,1表示列
# 删除行
shopping_carts = shopping_carts.drop(['store3', 'watch'], axis=0)
rename()
# 更改列标签
shopping_carts = shopping_carts.rename(columns={'Bob': 'Jey'})
# 更改行标签
shopping_carts = shopping_carts.rename(index={'bike': 'hats'})
iterrows(): 将DataFrame迭代为(insex, Series)对。
iteritems(): 将DataFrame迭代为(列名, Series)对
itertuples(): 将DataFrame迭代为元祖。
示例代码:
import pandas as pd
inp=pd.DataFrame([{'c1':10,'c2':20},
{'c1':50,'c2':60},
{'c1':70,'c2':80}])
print(inp)
print('#'*50)
for idx,s in inp.iterrows():
print('idx',idx)
print(s)
print('#'*50)
for col_name,v in inp.iteritems():
print('col_name',col_name)
print(s)
print('#'*50)
for tu in inp.itertuples():
print(tu)
输出:
c1 c2
0 10 20
1 50 60
2 70 80
##################################################
idx 0
c1 10
c2 20
Name: 0, dtype: int64
idx 1
c1 50
c2 60
Name: 1, dtype: int64
idx 2
c1 70
c2 80
Name: 2, dtype: int64
##################################################
col_name c1
c1 70
c2 80
Name: 2, dtype: int64
col_name c2
c1 70
c2 80
Name: 2, dtype: int64
##################################################
Pandas(Index=0, c1=10, c2=20)
Pandas(Index=1, c1=50, c2=60)
Pandas(Index=2, c1=70, c2=80)
统计 NaN 数量:isnull().sum().sum
# 数值转化为 True 或者 False
print(store_items.isnull())
# 每一列的 NaN 的数量
print(store_items.isnull().sum())
# NaN 总数
print(store_items.isnull().sum().sum())
统计非 NaN 数量:count(axis=0/1)
# 每一行非 NaN 的数量,通过列统计
print(store_items.count(axis=1))
# 每一列非 NaN 的数量,通过行统计
print(store_items.count(axis=0))
删除具有NaN值的行和列:dropna(axis=0/1, inplace=True/False) inplace默认False,原始DataFrame不会改变;inplace为True,在原始DataFrame删除行或者列
# 删除包含NaN值的任何行
store_items.dropna(axis=0)
# 删除包含NaN值的任何列
store_items.dropna(axis=1, inplace=True)
将 NaN 替换合适的值:fillna()
# 将所有 NaN 替换为 0
store_items.fillna(value=0)
# 前向填充:将 NaN 值替换为 DataFrame 中的上个值,axis决定列或行中的上个值
store_items.fillna(method='ffill', axis=1)
# 后向填充:将 NaN 值替换为 DataFrame 中的下个值,axis决定列或行中的下个值
store_items.fillna(method='backfill', axis=0)
csv 格式文件,每一行都是用逗号隔开:read_csv()
# 读取 csv 文件,第一行作为列标签
data = pd.read_csv('data.csv')
print(data)
print(data.shape)
print(type(data))
读取前 N 行数据:head(N)
# 读取头 3 行数据
print(data.head(3))
读取最后 N 行数据:tail(N)
# 读取后 5 行数据
print(data.tail(5))
检查是否有任何列包含 NaN 值:isnull().any() 类型 bool
# 检查任何列是否有 NaN 值,返回值:bool
print(data.isnull().any())
数据集的统计信息:describe()
# 获取 DataFrame 每列的统计信息:count,mean,std,min,25%,50%,75%,max
# 25%:四分之一位数;50%:中位数;75%:四分之三位数
print(data.describe())
# 通过统计学函数查看某个统计信息
print(data.max())
print(data.median())
数据相关性:不同列的数据是否有关联,1 表明关联性很高,0 表明数据不相关。corr()
# 数据相关性
print(data.corr())
数据分组:groupby(['lable1', 'lable2'])
# 按年份分组,统计总薪资
data.groupby(['Year'])['Salary'].sum()
# 按年份分组,统计平均薪资
data.groupby(['Year'])['Salary'].mean()
# 按年份,部门分组,统计总薪资
data.groupby(['Year', 'Department'])['Salary'].sum()
将DataFrame中的某一列替换为索引:
df.set_index("period",inplace=True)
从现有的DataFrame中切出一个索引:
s1=pd.Series(df.loc['202012']['item'])
其中:’202012’代表索引过滤为202012的,item为具体需要新建索引的列(因为本质上Series对象即为DataFrame的某一列)
标签索引与切片:df.loc[row_ indexer, column_indexer]
位置索引与切片:df.iloc[row_ indexer, column_indexer]
shift函数
dataframe[“col”].shift(-1): 某列整体前(上)移 1 位,空缺出来的用Nan补齐
dataframe[“col”].shift(1): 某列整体后(下)移 1 位,空缺出来的用Nan补齐
假设df是一个现成的DataFrame,一般使用df.T函数进行行列转置
df_T = pd.DataFrame(df.values.T,columns=index_row,index=index_colums)
print(df_T)
1、 按索引进行排序
a = np.arange(9).reshape(3,3)
data = DataFrame(a,index=["0","2","1"],columns=["c","a","b"])
#按行的索引升序进行排序,默认按行,升序
print(data.sort_index())
'''
c a b
0 0 1 2
1 6 7 8
2 3 4 5
'''
#按行的索引按降序进行排序
print(data.sort_index(ascending=False))
'''
c a b
2 3 4 5
1 6 7 8
0 0 1 2
'''
#按列升序的索引进行排序
print(data.sort_index(axis=1))
'''
a b c
0 1 2 0
2 4 5 3
1 7 8 6
'''
#按列降序的索引进行排序
print(data.sort_index(ascending=False))
'''
c a b
2 3 4 5
1 6 7 8
0 0 1 2
'''
2、按值进行排序
a = [[9,3,1],[1,2,8],[1,0,5]]
data = DataFrame(a, index=["0", "2", "1"], columns=["c", "a", "b"])
#按指定列的值大小顺序进行排序
print(data.sort_values(by="c"))
'''
c a b
2 1 2 8
1 1 0 5
0 9 3 1
'''
print(data.sort_values(by=["c","a"]))
'''
c a b
1 1 0 5
2 1 2 8
0 9 3 1
'''
#按指定行值进行排序
print(data.sort_values(by="0",axis=1))
'''
b a c
0 1 3 9
2 8 2 1
1 5 0 1
'''
注意:对DataFrame的值进行排序的时候,我们必须要使用by指定某一行(列)或者某几行(列),如果不使用by参数进行指定的时候,就会报TypeError: sort_values() missing 1 required positional argument: 'by'。使用by参数进行某几列(行)排序的时候,以列表中的第一个为准,可能后面的不会生效,因为有的时候无法做到既对第一行(列)进行升序排序又对第二行(列)进行排序。在指定行值进行排序的时候,必须设置axis=1,不然会报错,因为默认指定的是列索引,找不到这个索引所以报错,axis=1的意思是指定行索引。
排名和排序有点类似,排名会有一个排名值(从1开始,一直到数组中有效数据的数量),它与numpy.argsort的间接排序索引差不多,只不过它可以根据某种规则破坏平级关系。
a = [[9, 3, 1], [1, 2, 8], [1, 0, 5]]
data = DataFrame(a, index=["0", "2", "1"], columns=["c", "a", "b"])
print(data)
'''
c a b
0 9 3 1
2 1 2 8
1 1 0 5
'''
#默认按列进行排名
print(data.rank())
'''
c a b
0 3.0 3.0 1.0
2 1.5 2.0 3.0
1 1.5 1.0 2.0
'''
#按行进行排名
print(data.rank(axis=1))
'''
c a b
0 3.0 2.0 1.0
2 1.0 2.0 3.0
1 2.0 1.0 3.0
'''
method参数和ascending参数的设置与Series一样。
数据规整的一般分类:
清理
转换
合并
重塑
对指定数据(如缺失数据、重复数据)进行处理(检查、替换、删除)
缺失值的表示:np.nan
检查缺失值:isnull(),notnull(),info()
删除缺失值:dropna()
填充缺失值:fillna()
替换值(填充缺失值是替换值的一种情况):replace()
------------------------------
移除重复数据
检测和过滤异常值
实例代码:
a = np.array([2,4,5,7,8,9])
a + 10
# result array([12, 14, 15, 17, 18, 19])
b = np.array([None,1,4,6,8,4,23,67])
b + 10
# result TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
结论:缺失值导致报错
缺失值运算不会报错,和缺失值进行运算,结果还是缺失值
a = np.array([np.nan,1,4,5])
a + 10
a.sum() # 任何数组和缺失值计算,结果还是缺失值
np.nansum(a)
np.nanmean(a) # result 3.3333333333333335 ,缺失值不参与运算
nan专有运算方法,会跳过缺失值,直接计算正常值,缺失值不参与运算
np.nansum(c)
np.nanmean(c)
Pandas中,不论缺失值是 None 还是 np.nan ,都会转化为 NaN 的形式
NaN:非数字,not a number,Pandas中它表示缺失或NA值,便于被检测出来
本质上就是np.nan
Pandas的对象可以跳过缺失值直接进行运算
b = pd.Series([1,2,np.nan,4,None,6])
b+10
#reslut
#0 11.0
#1 12.0
#2 NaN
#3 14.0
#4 NaN
#5 16.0
b.mean() # 4.0
# 缺失值赋值
b[0] = np.nan
c = pd.DataFrame([[1,np.nan,3], [4,5,6], [np.nan,8,9]])
c.sum(axis=1)
检查单个空值
单个空值,底层类型为 np.nan,不能直接比较是否相同
# 单个空值,底层类型为 np.nan,不能直接比较是否相同
np.nan == np.nan
# 单个np.nan空值,可以用 np.isnan() 方法判断是否是空值
np.isnan(np.nan)
# 整体判断,表格中各列缺失值情况
http://c.info() # dataframe
np.isnan(c)
np.isnan(b) # series
isnull()和notnull()
isnull():缺失值返回True,正常值返回False
notnull():正常值返回True,缺失值返回False
b.isnull()
# 过滤非空
b[-b.isnull()]
b.notnull() # 同上, 选中所有非缺失值
b[b.notnull()]
# dataframe 使用isnull notnull的时候无法具体分清
c.isnull()
c[c.isnull()]
c.notnull()
c[c.notnull()]
结论:DataFrame不能通过布尔查询方式过滤缺失值,必须使用Pandas的特定方法过滤
查到缺失值后,Series可以直接过滤,DataFrame需要进一步处理(填充或删除)
# series
b.dropna()
# 等同于上:查询所有非缺失值
b[b.notnull()]
# dataframe
c.dropna() # 默认按行
c.dropna(axis=1) # 按列删除
# 增加一列全部为缺失值的数据
c[3] = np.nan
# 行或列,有1个缺失值即删除
c.dropna(axis=1) # 简写,默认
c.dropna(axis=1, how='any')
# 行或列必须全部都是缺失值才删
c.dropna(axis=1, how='all')
c.dropna(thresh=3) # 行非缺失值数量大于等于3个,保留
缺失值问题除了删除所在行列以外,还可以通过填充值解决
fillna()函数参数
c.loc[0, 1] = np.nan
c.loc[1:3,0] = np.nan
c.at[3,3] =100 #导致出现了第四行数据
c[3] = np.nan
c.fillna(method='ffill')
c.fillna(method='ffill',limit=3) # 设置填充改变的数量,limit=3每一列可以有三行数据改变
利用fillna方法填充缺失数据是值替换的一种特殊情况, replace方法用作替换值更简单、更灵活
data = pd.Series([1,-999,2,-999,-1000,3])
# 替换单值
data.replace(-999, np.nan)
# 替换多值, 多个值替换为1个
data.replace([-999, -1000], np.nan)
# 多个值替换为不同数值
data.replace([-999, -1000], [0, 1])
data.replace({-999: 0, -1000: 1})
#dataframe也是如此,直接替换值
c.replace(1,-1)
map除了自定义函数运算,还是一种映射转换元素以及其他数据清理工作的便捷方式
a = pd.DataFrame([['鬃刷','皮带','煎蛋','观赏'],[10,20,30,40]]).T # 转置
y = {'鬃刷': '猪', '皮带': '牛', '观赏': '鱼', '衣服': '棉花'}
a[0].map(y)
移除DataFrame的重复行
data = pd.DataFrame({'k1':['one'] * 3 + ['two'] * 4,'k2':[1,1,2,3,3,4,4]})
# 布尔型Series,各列重复值交集
data.duplicated()
# 重复行的移除
data.drop_duplicates()
data[-data.duplicated()]
# 移除自定义列重复行
data.drop_duplicates('k1') 或data.drop_duplicates(['k1']) (多个列可以在list中增加)
#keep : {‘first’, ‘last’, False},
# first默认留下第一次出现的值
data.drop_duplicates(['k1', 'k2'])
data.drop_duplicates(['k1', 'k2'], keep='first')
# last,留下最后一次出现的值
data.drop_duplicates(['k1', 'k2'], keep='last')
# 保留非全列的行数据时,结果行会不同
data.drop_duplicates(['k1'])
data.drop_duplicates(['k1'], keep='last')
# False,删掉所有重复值
data.drop_duplicates(['k1', 'k2'], keep=False)
obj = pd.Series(range(5), index = ['a','a','b','b','c'])
obj['a']
obj[obj.duplicated()]
obj[~(obj.index.duplicated())] # 查询不重复索引对应的值
过滤或变换异常值(outlier)在很大程度上就是运用数组运算
例子:一个含有正态分布数据的DataFrame
data = pd.DataFrame(np.random.randn(1000, 4))
data[0:3]
data[2][(data[2]>3) | (data[2]<-3)]
data[2][np.abs(data[2])>3]
# 找出全部绝对值大于3的值所在的行
data[np.abs(data)>3].dropna(how='all')
data[np.abs(data) > 3]
data[np.abs(data) > 3].any(axis=1) #前面的条件只要有一个生效就是true,一个没有就是False
data[data[np.abs(data) > 3].any(axis=1)]
a = np.array([3, -4, 7, -100])
np.sign(a) # 判断数据正负,正数1,负数-1,生成一个对应数据的1,-1数据
# 将数据范围限制在3到-3之间(大于3的改为3,小于-3的改为-3)
np.sign(data)
data[np.abs(data) > 3] = np.sign(data) * 3
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。