pandas
numpy https://www.cnblogs.com/wwg945/articles/8661583.html
Series对象
Series 是一种一维数组,和 NumPy 里的数组很相似。事实上,Series 基本上就是基于 NumPy 的数组对象来的。和 NumPy 的数组不同,Series 能为数据自定义标签,也就是索引(index),然后通过索引来访问数组中的数据。
a = pd.Series(data=[100,200,300],index=["5月","6月","7月"]) print(a[0],a["5月"])
上面的 data 参数可以是任意数据对象,比如字典、列表甚至是 NumPy 数组,而index 参数则是对 data 的索引值,类似字典的 key。
用字典生成Series的时候, 也可以指定索引, 当索引中值不存在与字典的键的时候则次索引的值标记为NA.
a = pd.Series(data={"name":"li","sex":"男"},index=["name","age","sex"]) print(a)
通过函数pandas.isnull和pandas.notnull可以知道那个字段是空, 那个字段不是空
pd.isnull(a) ''' name False age True sex False dtype: bool ''' pd.notnull(a) ''' name True age False sex True dtype: bool '''
通过索引可以访问Series中的元素
a = pd.Series(data={"name":"li","sex":"男"},index=["name","age","sex"]) a[["name","age"]] ''' name li age NaN dtype: object ''' a["name"] # li
获取所有的值
a.values # array(['li', nan, '男'], dtype=object)
获取所有的索引
a.index # Index(['name', 'age', 'sex'], dtype='object')
Series也可以使用bool索引
a = pd.Series(data={"2015":998,"2016":990,"2014":500}) a>990 ''' 2015 True 2016 False 2014 False dtype: bool '''
运算
# 两个不同的Series是按照index来相加的 a = pd.Series(data={"2015":998,"2016":990,"2014":500}) b = pd.Series(data={"2013":998,"2014":990,"2015":500}) a+b # 相同索引值元素相加, 不相同的会设置成NAN ''' 2013 NaN 2014 1490.0 2015 1498.0 2016 NaN dtype: float64 '''
DataFrame
DataFrame对象是一种二维数组, 数据以表格的形式存储, 分成若干行和列。通过 DataFrame,你能很方便地处理数据。常见的操作比如选取、替换行或列的数据,还能重组数据表、修改索引、多重筛选等。
创建DataFrame对象
通过Series来创建DataFrame
info = {"name":pd.Series(["金角","银角","太白","小旋风"]), "age":pd.Series(['998','1000','5000','200']), "weapon":pd.Series(["幌金绳","紫金葫芦","七星剑","号令旗"])} pd.DataFrame(info) # 这个字典的键是每一列的名称, 相同位置的元素成为行
通过字典来创建DataFrame, 结果与上面相同, 行的索引为数字索引
info = {"name":["金角","银角","太白","小旋风"], "age":['998','1000','5000','200'], "weapon":["幌金绳","紫金葫芦","七星剑","号令旗"]} a = pd.DataFrame(info)
像上面那种其实已经有列的名字了 ,另外还可以根据二维列表来创建DataFrame对象, 不过这样行和列的索引就都变成了数字了
df = pd.DataFrame(np.random.randn(6,4)) print(df)
DataFrame也可以设置行索引, 不过一般行数是不确定的, 这个一般也不设置
info = {"name":["金角","银角","太白","小旋风"], "age":['998','1000','5000','200'], "weapon":["幌金绳","紫金葫芦","七星剑","号令旗"]} a = pd.DataFrame(info,index=["老大","老二","老三","老四"])
不仅仅是可以设置行索引, 还可以设置列索引
df = pd.DataFrame(np.random.randn(6,4), columns=list('ABCD')) print(df)
列操作
获取列索引
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) column = df.columns print(column)
查看每一列的类型
df = pd.DataFrame(np.random.randn(6,4), columns=list('ABCD')) print(df.dtypes)
要获取一列的数据,还是用中括号 [] 的方式, 当取1列是返回的Series对象
info = {"name":["金角","银角","太白","小旋风"], "age":['998','1000','5000','200'], "weapon":["幌金绳","紫金葫芦","七星剑","号令旗"]} a = pd.DataFrame(info) a["name"] type(a["name"])
获取多列时,返回的是DataFrame类型
info = {"name":["金角","银角","太白","小旋风"], "age":['998','1000','5000','200'], "weapon":["幌金绳","紫金葫芦","七星剑","号令旗"]} a = pd.DataFrame(info) a[["name","age"]] type(a[["name","age"]])
添加一列, 可以定义一个Series(或者是字典),并放入一个列中
info = {"name":["金角","银角","太白","小旋风"], "age":['998','1000','5000','200'], "weapon":["幌金绳","紫金葫芦","七星剑","号令旗"]} year = ["0000","0001","0002","0003"] a = pd.DataFrame(info) a["year"] = year
或者是通过已存在的两列生成一列
info = {"name":["金角","银角","太白","小旋风"], "age":['998','1000','5000','200'], "weapon":["幌金绳","紫金葫芦","七星剑","号令旗"]} year = ["0000","0001","0002","0003"] a = pd.DataFrame(info) a["year"] = year a["year_age"] = a["year"]+a["age"]
删除行或列
drop方法可以删除通过指定axis来删除行或列. 0对应的行, 1对应的是列
# 删除第0行 info = {"name":["金角","银角","太白","小旋风"], "age":['998','1000','5000','200'], "weapon":["幌金绳","紫金葫芦","七星剑","号令旗"]} year = ["0000","0001","0002","0003"] a = pd.DataFrame(info) a.drop(0,axis=0) # 删除name列 info = {"name":["金角","银角","太白","小旋风"], "age":['998','1000','5000','200'], "weapon":["幌金绳","紫金葫芦","七星剑","号令旗"]} year = ["0000","0001","0002","0003"] a = pd.DataFrame(info) a.drop("name",axis=1)
要注意的是drop返回的内容是修改后的, 并不会对原数据进行修改, 除非加上inplace=True 参数
行操作
获取
df = pd.DataFrame(np.random.randn(6,4), index=pd.date_range("20130101",periods=6) , columns=list('ABCD')) # 获取前几行, 默认5, 可以指定行数 head= df.head(3) # 获取后几行, 默认5, 可以指定行数 tail = df.tail(3) # 通过切片获得行 df[0:3] # 可以通过行的数字序号 df['20130102':'20130104'] # 也可以通过行的索引
获取行索引
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) index = df.index print(index)
添加一行
df = pd.DataFrame(np.random.randn(2,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) df.append(df.iloc[1])
关于选取
在Dataframe中选取数据大抵包括3中情况:
1)行(列)选取(单维度选取):df[]。这种情况一次只能选取行或者列,即一次选取中,只能为行或者列设置筛选条件(只能为一个维度设置筛选条件)。
2)区域选取(多维选取):df.loc[],df.iloc[],df.ix[]。这种方式可以同时为多个维度设置筛选条件。
3)单元格选取(点选取):df.at[],df.iat[]。准确定位一个单元格。
行列的选取:
选行
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) print(df[0:1]) # 选行的时候不能直接使用索引, 使用索引的话就成了选列了, 数字索引,顾头不顾尾 print(df['20130102':'20130104']) # 设置的行索引, 顾头又顾尾 print(df[[True,True,True,False,False,False]]) # 布尔索引, 返回True的行 index = df["C"] >0.5 # print(index) print(df[index]) # 通过运算构建布尔索引 print(df[(df["C"] >0.5) & (df["C"] <0.7) ]) # 且, print(df[(df["C"] <0.5) | (df["C"] >0.7) ]) # 或
选列
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) print(df["A"]) # 选单列 print(df[["A","B"]]) # 选多列
区域选取
区域选取可以从多个维度(行和列)对数据进行筛选,可以通过df.loc[],df.iloc[],df.ix[]三种方法实现。采用df.loc[],df.iloc[],df.ix[]这三种方法进行数据选取时,方括号内必须有两个参数,第一个参数是对行的筛选条件,第二个参数是对列的筛选条件,两个参数用逗号隔开。df.loc[],df.iloc[],df.ix[]的区别如下:
df.loc[]只能使用标签索引,不能使用整数索引,通过便签索引切边进行筛选时,前闭后闭。
df.iloc[]只能使用整数索引,不能使用标签索引,通过整数索引切边进行筛选时,前闭后开。;
df.ix[]既可以使用标签索引,也可以使用整数索引。
下面就只示范一种就可以了, 区域选取更类似于花式索引, 选行和选列通过,隔开
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) print(df.iloc[0,:]) # 第一行所有列 print(df.iloc[[0,1,3],:]) # 指定三行的所有列 print(df.iloc[0:3,:]) # 前三行的所有列 # 后面布尔和组合的就不写了 print(df.iloc[:,1]) # 第一列 # 不想写了, 其实都是差不多的, 补充一个取值的吧, 选行和列如果简单的运算不够用的话可以指定函数 # 实际上还是布尔索引 print(df[lambda df:df['A'] > 0.5]) # 选取A行大于0.5的
单元格选取
单元格选取包括df.at[]和df.iat[]两种方法。df.at[]和df.iat[]使用时必须输入两个参数,即行索引和列索引,其中df.at[]只能使用标签索引,df.iat[]只能使用整数索引。df.at[]和df.iat[]选取的都是单个单元格(单行单列),所以返回值都为基本数据类型。
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) print(df.iat[0,0])
关于布尔索引与缺失值填充
dataframe中不仅仅可以对某一列(行无法单独取)进行运算来获得布尔索引, 还可以对整个DataFrame进行运算来获得布尔索引(不要问我怎么对行运算获得布尔索引, 我不会告诉你行列转换的)
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) print(df["A"]>0) print(df[df["A"]>0]) print(df>0) print(df[df>0]) # 这样得到的值中不满足条件的就会变成NAN, 下面就来介绍对于缺失值的处理 df1 = df[df>0] # 方案一: 删除缺少数据的行 df1.dropna(how="any") # any是行或者列包含nan的, axis默认=0,删除行 # 方案二: 填写填充的数据 df1.fillna(value=5) # 除设置指定值外, 还可以设置附近的值来填充 df1 = df1.fillna(method='bfill',axis=0,limit=1) # 那纵向后面的limit个元素的平均值填充 df1 = df1.fillna(method='ffill',axis=0,limit=1) # 那纵向前面的limit个元素的平均值填充 print(df1) # 获取为nan的布尔索引 print(pd.isna(df1))
其他方法
apply(): 将DataFrame的一行或一列传入指定的函数中
import pandas as pd import math ls = [ [1,2,3,4,5], [4,5,6,7,8], [3,5,8,3,1], ] df = pd.DataFrame(ls) # axis=0 将函数应用于每一列 # axis=1 将函数应用于每一行 print(df.apply(lambda s:s.max()))
data_range: 创建时间日期的索引列
import numpy as np import pandas as pd dates = pd.date_range("20130101",periods=6) # print(dates) # 默认时间差为天, 通过freq可以设置, 常用的有D:日, W:周, # 更多就参见http://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#timeseries-offset-aliases dates = pd.date_range("20130101",periods=6,freq="W") # print(dates) # 可以用这一列做为DataFrame的索引列 df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD')) print(df)
显示数据值(无索引)
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) value = df.values print(value)
显示数据的统计
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) desc = df.describe() print(desc, type(desc)) # 返回的也是一个dataframe,
行列转换
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) fd = df.T print(fd)
排序
df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) # 按轴排序 df = df.sort_index(axis=1, ascending=False) # 将列排序,降序 print(df) df = df.sort_index(axis=0, ascending=False) # 将行排序 print(df) # 按值排序 df = pd.DataFrame(np.random.randn(6,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) df = df.sort_values(by="B") # 按照B列中的内容将行排序 print(df)
去重
drop_duplicate去除特定列下面的重复行。返回DataFrame格式的数据。
# 其中包含三个参数 subset : column label or sequence of labels, optional # 用来指定特定的列,默认所有列 keep : {‘first’, ‘last’, False}, default ‘first’ # 删除重复项并保留第一次出现的项 inplace : boolean, default False # 是直接在原来数据上修改还是保留一个副本
实践
import pandas as pd import math df = pd.DataFrame({"A":[1,1,2,2],'B':["a","b","c","c"]}) print(df.drop_duplicates("A","first")) print(df.drop_duplicates(["A","B"],"last"))
合并与分组
合并
# 构造三个两行四列的DataFrame df1 = pd.DataFrame(np.random.randn(2, 4)) df2 = pd.DataFrame(np.random.randn(2, 4)) df3 = pd.DataFrame(np.random.randn(2, 4)) # 使用concat # print(pd.concat([df1,df2,df3])) # 此时是固定列, 纵向添加 通过设置axis改为固定行,横向添加 # print(pd.concat([df1,df2,df3], axis=1)) # 此外还可以指定join参数, 默认的是outer, 得到的是并集, 可以设置为inner, 得到的就是交集了 df1 = pd.DataFrame(np.random.randn(2, 4), columns=list("ABCD")) df2 = pd.DataFrame(np.random.randn(2, 4), columns=list("CDEF")) # 通过内联得到的只有同名的列, 外联会补充NAN print(pd.concat([df1, df2], join="inner")) # 使用merge, merge更像是数据库的连表 df1 = pd.DataFrame({"name": ["金角", "银角", "太白", "小旋风"], "age": ['998', '1000', '5000', '200']}) df2 = pd.DataFrame({"name": ["金角", "银角", "太白", "黑旋风"], "weapon": ["幌金绳", "紫金葫芦", "七星剑", "号令旗"]}) print(pd.merge(df1,df2, on="name")) # 用name将两个表连接 # 当关联的两行或者两列不是同名时, 可以通过设置left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列
分组, 不过这里的输出你是看不见的
df = pd.DataFrame({'A': ['a', 'b', 'a', 'c', 'a', 'c', 'b', 'c'], 'B': [2, 8, 1, 4, 3, 2, 5, 9], 'C': [102, 98, 107, 104, 115, 87, 92, 123]}) # 按某一列分组 print(df.groupby("A")) # 获取zhe这一列某一个值对应的行 print(df.groupby("A").get_group("a")) # 按多列进行分组 print(df.groupby(["A","B"])) # 分组后是可以选列的 print(df.groupby("A")["B"]) print(df.groupby("A")[["A","B"]]) # 选多列
聚合方法
sum(),mean(),max(),min(),size(),describe()
df = pd.DataFrame({'A': ['a', 'b', 'a', 'c', 'a', 'c', 'b', 'c'], 'B': [2, 8, 1, 4, 3, 2, 5, 9], 'C': [102, 98, 107, 104, 115, 87, 92, 123]}) print(df.groupby("A")[["A","B"]].mean()) # 平均值 print(df.groupby("A")[["A","B"]].sum()) # 求和 print(df.groupby("A")[["A","B"]].max()) # 最大值 print(df.groupby("A")[["A","B"]].mean()) # 平均值 # size跟count的区别: size计数时包含NaN值,而count不包含NaN值 print(df.groupby("A")[["A","B"]].size()) # 数量 print(df.groupby("A")[["A","B"]].count()) # 数量 # 分组运算方法, 为不同的列使用不同的聚合函数 print(df.groupby("A")[["A","B"]].agg({"A":"sum","B":"max"})) # 也可以求一列的多个聚合函数 print(df.groupby("A")["B"].agg({"sum":"sum","max":"max"}))
数据的读取和写入
CSV
df = pd.DataFrame(np.random.randn(2,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) # 读取 pd.read_csv("file") # 写入 df.to_csv("file")
Excel
df = pd.DataFrame(np.random.randn(2,4),index=pd.date_range("20130101",periods=6), columns=list('ABCD')) # 读取 pd.read_excel("file",sheetname) # 写入 df.to_excel("file",sheetname)
最后来几道题吧
一: 有一个N行M列的二维数组, 写一个函数, 把值大于3的行取出来, 组成一个X行M列的新数组
import pandas as pd ls = [ [1,2,3,4,5], [4,5,6,7,8], [3,5,8,3,1], ] def filter(array): df = pd.DataFrame(array) # 首先df.T, 行转列, 然后找最小值大于3的列, 得到布尔索引, 然后用布尔索引直接取 return df[df.T.min()>3].values.tolist() ret = filter(ls) print(ret)