Series、DataFrame:Series可以当成1维数组
from pandas import Series
a= Series(data=[1,2,3,'four'])
a= Series(data=[1,2,3,'four'],index=['a','b','c','d'])
dic = {‘chinese’:99,‘math’:100,‘pe’:98}
a= Series(data=dic)
a[0:2] # 切片
a.shape
a.size # 返回大小
a.index #返回索引
a.values # 返回值
a.dtype # 返回类型
Series常用的方法
head()、# 前n个数据
tail()、 # 后n个数据
unique()、# 去重
isnull()、 # y用于判断每一个元素是否为空,为空返回true,否则返回false
notnull()、 # y用于判断每一个元素是否不为空,不为空返回true,否则返回false
add()、sub()、mul()、div() # 加减乘除
Series算术运算
a+b
DataFrame
是一个二位数组。
行索引:index、列索引:columns、值:values,shape:维度
初始化
df = DataFrame(data = [[1,2,3],[4,5,6]])
df = DataFrame(data = np.random.randint(0,100,size=(6,4)))
dic = {
”name":["zhangsan","lisi","wanglao"],
"salary":[1000,2000,3000]
}
df = DataFrame(data=dic,index=["a","b","c"])
df[0].dtype
df= DataFrame(data=np.random.randint(60,100,size=(8,4)),columns=["a","b","c","d"])
df["a"] # 取单列,如果df有显示的索引,通过索引机制去行或者列的时候只可以使用显示索引。
df[['a','c']] # 取多列
df.iloc[0] #取单行
df.iloc[[0,2,5]] #取多行
- iloc : 通过隐式索引取行
- loc : 通过显示索引取行
df.iloc[0,2] #取单个元素,第0行,2列的值。
df.loc[0,‘a’] #取单个元素.
df.iloc[[1,3,5],2] #取多个元素.
切片
df[0:2] # 切行, 0、1 行的数据
df.iloc[:,0:2] #切列,0、1 列
df 索引和切片操作
索引:
df[col]:取列
df.loc[index]:取行
df.iloc[index,col]:取元素
df[index1:index3]:切行
df.iloc[:,col1:col3]:切列
运算:同series 相同
dic = {
”name":["zhangsan","lisi","wanglao"],
"salary":[1000,2000,3000],
"time":['2024-1-1','2024-2-1','2024-3-1']
}
df = DataFrame(data=dic,index=["a","b","c"])
df.loc['zhangsan','salary'] = 3500
df['salary'] += 100
df['time'] = pd.to_datetime(df["time"]) #将 time 列的数据转换成时间序列类型
# 将time 列作为源数据的行索引
df.set_index('time',inplace = True)
分析
股票分析
-- 聚宽, 也有很多金融数据
- -tushare: 财经数据接口包, 可以上官网看
pip install tushare
import tushare as ts
import pandas as pd
import numpy as np
# 获取某只股票的历史行情
df = ts.get_k_data(code=''600519",start='2000-01-01')
# 将数据存储过本地
df.to_csv("./maotai.csv")
# 将本地的存储的数据读到df
df = pd.read_csc("./maotai.csv")
df.head()
# 删除df 中指定的一列
df.drop(labels="Unamed:0", axis =1,inplace =true)
# 查看每一列数据类型
df['date'].dtype
df.info()
# 将time转换为时间序列
df["date"] = pd.to_datetime(df["date"])
df.set_index("date", inplace=true)
# 输出该股票所有收盘比排盘上涨3%以上的日期,(收盘-开盘)/开盘>0.03
df2 = (df[“close”] - df['open'])/ df['open'] >0.03
# 在分析过程中如果产生了boolean 值,则下一步可作为源数据的行索引
df.loc[df2 ].index # 过滤后的行数据的索引
# 输出该股票所有开盘比前日收盘跌幅超过2% 的日期, shift() ,是数据下移
df.loc[(df[“open”] - df['close'].shift(1))/ df['close'].shift(1) < -0.02].index
# 需求:假如从 2010-1-1 开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,至今为止,总收益是多少? 2010-2020
1手股票:100 支股票
new_df = df['2010-01':'2020-02']
# 买股票:找每个月的第一个交易日对应的行数据(),即每月的第一行数据
df_month = new_df.resample('M').first() # 数据的重新取样,知识点:resample
# 买入股票花费的总金额
cost = df_month[''open"].sum()*100
#卖出股票到手的钱
df_year = new_df.resample('A').last()[:-1] # 注意最后一年的数据要去掉,还没有到年末
# 卖出到手的钱
resv = df_year['open'].sum()*1200
# 手中剩余股票,需要估价,计算到总收益中
left_amount= 200 * new_df['close][-1]
#计算总收益
resv + left_amount -cost
# 双均线策略制定,引用上方的 new_df
计算该股票的历史数据的5日均线和60日均线, 5、10、30、60、120、240
# 均线的计算方法: MA = (C1+C2+C3+...+Cn)/N ,C是某日收盘架,N是移动平均周期(天数)
# 均线的计算方法:
MA5 = df['close'].rolling(5),mean() # 计算5日的均值
MA30 = df['close'].rolling(30),mean() # 计算5日的均值
import matplotlib.pyplot as plt %matplotlib inline
plt.plot(ma5[:30])
plt.plot(ma30[:30])
# 分析出所有金叉和死叉日期
金叉: s1 = ma5<ma30 s2 = ma5 > ma30
ma5 = ma5[30:]
ma30 = ma30 [30:] # 因为前30 是Non值
s1 = ma5<ma30
s2 = ma5 > ma30
death_ex = s1 &s2.shift(1) # 判定死叉的条件
df.loc[death_ex].index
golden_ex = ~(s1 | s2.shift(1) ) # 判定金叉的条件
golden_date = new_df.loc(golden_ex ).index
# 如果冲2010-1-1 开始,初始资金为 100000元,金叉尽量买入,死叉全部卖出,则到今为止,总收益是如何?
s1 = Series(data=1,index = golden_date) # 1作为金叉的标识
s2 = Series(data=0,index = death_date) # 0作为死叉的标识
a = s1 .append(s2)
s = s.sort_inex() # 存储的是金叉和死叉的对应的时间
s = s['2010':'2020']
first_money = 10000
money = first_money
hold = 0
for i in s:
if i == 1: # i =0 (死叉:卖),=1(金叉:买)
time = s.index[i]
p = df.loc[time]['open']100 # 股票单价
hand_count = mone // (p*100)
hold = hand_count *100
money -= (hand_count *100 *p) # 减去卖股票的money
else:
death_time = death_time = s.index[i]
p = df.loc[time]['open'] # 股票单价
money += (hand_count *100 *p)
hold = 0
# 如何判定最后哦一天金叉还是死叉
last_money = hold * df['close'][-1]
#总收益
money - last_money - first_money
数据清洗
- 原始数据中会存在缺失值
- 重复值
- 异常值
处理丢失的数据
有两种丢失数据:
- None, type(None) NoneType
- np.nan(NaN) , type(np.nan) float
区分:NAN可以参与运算,None 是不可以参与运算的。
在pandas中,如果遇到None,则会将其强转成NAN
np.nan +1 = nan
isnull、notnull、any、all、dropna、fillna
规律:isnull >> any ,notnull >>all
方式1:对空值进行过滤(删除空所在的行数据)
isnull(元素是否为空)、notnull(元素不为空)、any(检测行或者列中是否存在True)、all
df.isnull().any(axis=1)
df.loc[df.isnull().any(axis=1)] # true对应的行数数据就是存在缺失值的行数据
drop_index = df.loc[df.isnull().any(axis=1)] .index # 即将要删除的行索引
df.drop(labels=drop_index,axis=0) # 将缺失行进行删除
dropna :直接删除缺失的行或列
df.dropna(axis=0)
fillna
df.fillna(value=666)
df.fillna(method='ffill', axis=0) #method: ffill 、bfill # 使用水平方向进行填充
处理重复数据
df = DataFrame(data = np.random.randint(0,100,size=(8,4)) )
df.iloc[2] =[0,0,0,0]
df.iloc[4] =[0,0,0,0]
df.iloc[5] =[0,0,0,0]
df.drop_duplicates(keep='first') # 去掉重复数据,keep='last', keep = False
处理异常数据
级联操作
pd.concat、pd.append
pandas使用pd.concat函数,与np.concatenate 函数类似,只是多了一些参数:
- objs
- axis=0
- keys
- join='outer' ,'inner':表示的是级联的方式,outer 会将所有的项进行级联(忽略匹配和不匹配),而 inner 只 ignore-index =False。
匹配级联
df1 = pd.DataFrame(data=np.random.randint(5,3),columns=['A','B','C'])
df2 = pd.DataFrame(data=np.random.randint(5,3),columns=['A','D','C'])
pd.concat((df1,df2),axis=1)
pd.concat((df1,df2),axis=0)
不匹配级联
如果想保留数据的完整性,必须使用outer(外连接)
pd.concat((df1,df2),axis=0)
pd.concat((df1,df2),axis=0,join='inner')
append 函数的使用
df1.append(df2)
合并操作
merge与concat 的区别在于,merge 需要依据某一共同列进行合并
使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
注意每一列元素的顺序不要求一致。
df1 = DataFrame({"emlployee":["Bob","Jake","Lisa"],"group":["Accounting","Engineer","Teacher"]})
df2 = DataFrame({"emlployee":["Lisa","Jake","Bob"],"hire_date":["2021","2020","2009"]})
pd.merge(df1,df2,on="emlployee")pd.merge(df1,df2,left_on="df1col",right_on="df2col",how="outer")
人口分析
# 为找到这些state/region 的state上补上正确的值,从而去掉state的所有NaN
# 1、先给USA的全称对应的空值进行批量赋值
df1["state/region"]=='USA'
df1.loc[df1["state/region"]=='USA'] # 将usa对应的行数据取出
indexs = df1.loc[df1["state/region"]=='USA'].index
df1.iloc[indexs,"state"] = ”United States“
# 合并各州面积areas
pd.merge(df1,dfarea,how="outer")
# 去除含有缺失数据的行
df1.drop(labels=indexes,axis=0,inplace=True)
# 找出2010年的全民人口数据
df1.query('ages=="total" & year ==2010')
#人口密度
df1["密度"] = df1["人口数量"] / df1["面积"]
#排序
df1.sort_values(by="密度",axis=0,ascending=False).iloc[0]
pandas高级操作
替换操作
df.replace(to_replace=2,value ="two") # 把数据中整数 2替换 成”two“
df.replace(to_replace={1:"two"}) # 把数据中整数 2替换 成”two“
df.replace(to_replace={4:5},value="five") # 把数据中 4 列的 5 替换成”five“
映射
dic = {
”name“:["张三","李四","张四"],
"salary":[14000,15000,18000]
}
df = DataFrame(data=dic)
# 映射关系表
dic2 = {
"张三":"tom",
"李四":"jack"
}
df["engname"] = df["name"].map(dic)
map是series的方法,只能被series调用。
运算工具
# 该函数是我们指定的一个运算法则
def after_sal(s):
return s - (s-3000)*0.5
df["after_sal"] = df["salary"].map(after_sal) # 可以将df["salary"] 这个series中每一个元素作为参数计算
排序实现的随机抽样
- take()
- np.random.permutation()
df = DataFrame(data= np.random.randint(0,100,size=(100,3),columns=["A","B","C"] ))
# 生成乱序的随机序列
np.random.permutation(10)
df.take([2,0,1],axis=1) # 将原始数据打乱
df.take(np.random.permutation(3),axis=1) # 将原始数据打乱
df.take(np.random.permutation(3),axis=1).take(np.random.permutation(100),axis=0) [0:50]
数据的分类处理
核心:
- groupby()函数
- groups属性查看分组情况
dic={ "item":["apple","banana","orange","banana","orange","apple"], "price":[4,3,3,2.5,4,2], "color":["red","yellow","yellow","green","green","green"], "weight":[12,20,50,30,20,44] } df = pd.DataFrame(data= dic)df.groupby(by="item").groups # 查看详细的分组情况
# 想要水果重量进行分析
df.groupby(by="item").mean() # 查看字段是数字类型的平均值
df.groupby(by="item")["price"].mean() # 查看平均价
# 将计算出的平均重量汇总到源数据
avgprice_dict = df.groupby(by="item")["price"].mean().to_dict()
df["color"].map(avgprice_dict )
高级数据聚合
def func(s):
pass
return
df.groupby(by="item")["price"].apply(func)
交叉表和透视表
数据加载
# 读取txt文档
pd.read_csv(".xxx.txt") # 数据少了1行,第一行是columns
pd.read_csv(".xxx.txt",header=None,sep='-') # 所有数据都是data
#读取sqllite3
import sqlite3 as sqlite3
conn = sqlite3.connect("./data/aa.sqlite")
sql_df = pd.read_sql("select* from tbla",conn)
# 将一个df中的数据值写入存储到db
df.to_sql("tbla",conn)
透视表
透视表是一种可以对数据动态排并且分类汇总的表格格式。或许大多数都在excel使用过透视表,在pandas中他被称作pivot_table.
透视表的优点:
- 灵活性高,可以随意定制你的分析计算要求
- 脉络清晰易于理解数据
- 操作性强,报表神器
df
pivot_table 有四个最重要的参数:index、values、columns、aggfunc
index:分类汇总的分类条件。每个pivot_table必须拥有一个index。
df.pivot_table(index=["对手","主客场"]) # 查看哈登对阵同一对手再不同主客场下的数据,分类条件为 对手、主客场,计算其各类得分的品均值。
# values :需要对计算的数据进行筛选。如果只需要哈登在主客场和不同胜负情况下的的得分、篮板、助攻三项数据。
df.pivot_table(index=["主客场","胜负"],values=["得分","篮板","助攻"])
Aggfunc参数:设置对数据聚合时进行的函数操作。当未设置时,默认aggrunc="mean"计算品均值。
df.pivot_table(index=["主客场","胜负"],values=["得分","篮板","助攻"],aggfunc="sum")
# 获取每个队主客场的总得分,在总得分的基础上进行了对手的分类
df.pivot_table(index=["主客场"],values="得分",aggfunc="sum",fill_value=0)
df.pivot_table(index=["主客场"],values="得分",columns="对手",aggfunc="sum",fill_value=0)
交叉表
交叉表时一种用于计算分组的特殊透视图,对数据进行汇总
pd.crosstab(index,columns)
- index:分组数据,交叉表的行索引
- columns:交叉表的列索引
# 求出各个性别抽烟的人数
pd.crosstab(df.smoke,df.sex)
pd.crosstab(df.age,df.sex)
示例:美国大选分析
# 对信息数据进行总览,查看是否存在缺失数据
df.info()
#用统计学指标快速描述数值型属性的概要
df.describe()
#空值处理
df.fillna(value="NOT PRIDER",inplace=True)
#异常处理
drop_indexs = df.loc[df.["conts_receipt_amt"]<=0]
df.drop[labels=drop_indexs ,axis=0,inplace=True]
parties= {
...}
df["party"] = df["can_nm"].map(parties)
df["party"].unique() # 查看party这一列中有哪些不同的元素
df["party"].value_counts() # 统计列中哥哥元素出现的次数
# 查看各个党派的收到的政治献金总数
df.groupby(by="party")[""contb_receipt_amt].sum()
df.groupby(by=[''dt","party"])[""contb_receipt_amt].sum()
# 将表中日期格式转换为:“yyyy-mm-dd”
def transdate(d):
day,month,year = d.spllit("-")
month = months[month]
return '20'+year+'-'+str(month)+'-'+day
df["dt"].map(transdate)
# 查看老兵主要支持谁