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)

  

 

posted @ 2019-04-23 14:14  瓜田月夜  阅读(147)  评论(0编辑  收藏  举报