Pandas

jzlixiao 2020-08-18

Pandas的数据结构

导入pandas:

import pandas as pdfrom pandas import Series,DataFrameimport numpy as np

Series

Series是一种类似与一维数组的对象,由下面两个部分组成:

  • values:一组数据(ndarray类型)
  • index:相关的数据索引标签

Series(
data=None,
index=None,
dtype=None,
name=None,
copy=False,
fastpath=False,
)

Series的创建

由列表或numpy数组创建

  • 默认索引为0到N-1的整数型索引
# 使用列表创建SeriesSeries(data=[1,2,3,])
0    11    22    3dtype: int64
Series(data=np.random.randint(0,100,size=(3)))
0    931    762    65dtype: int32
  • 可以通过设置index参数指定索引
Series(data=[1,2,3],index=[‘a‘,‘b‘,‘c‘]) #显式索引
a    1b    2c    3dtype: int64
============================================练习1:使用多种方法创建以下Series,命名为s1:  语文 150   数学 150   英语 150   理综 300   ============================================

Series的索引和切片

可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的是一个Series类型)。

(1) 显式索引:

  • 使用index中的元素作为索引值

  • 使用s.loc[](推荐):注意,loc中括号中放置的一定是显示索引

    注意,此时是闭区间

s = Series([1,2,3,4],index=[‘a‘,‘b‘,‘c‘,‘d‘])s
a    1b    2c    3d    4dtype: int64
s[1]  # 2,隐式索引:s[‘a‘]  # 1s.a  # 1  显示索引

隐式索引:

  • 使用整数作为索引值

  • 使用.iloc[](推荐):iloc中的中括号中必须放置隐式索引

    注意,此时是半开区间

s[1:3]   # 隐式切片s[‘a‘:‘c‘]  # 显示切片
a    1b    2c    3dtype: int64

Series的基本概念

可以使用s.head(),tail()分别查看前n个和后n个值

s.head(2)
a    1b    2dtype: int64

对Series元素进行去重

s = Series([1,1,1,2,3,3,3,3,2])s.unique()
array([1, 2, 3], dtype=int64)

使得两个Series进行相加。

当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况

s1 = Series([1,2,3],index=[‘a‘,‘b‘,‘c‘])s2 = Series([1,2,3],index=[‘a‘,‘d‘,‘c‘])s = s1 + s2s
a    2.0b    NaNc    6.0d    NaNdtype: float64

可以使用pd.isnull()pd.notnull(),或s.isnull(),notnull()函数检测缺失数据

s[[1,2]]  # 一次取多值s[[‘a‘,‘b‘]]s[[True,False,True,False]] # True将值保留,False:将值舍去。True:2,False:NaN,True:6,Flase:NaN。
a    2.0c    6.0dtype: float64
s.isnull()   # 检测每个元素,NOT NaN:False;NaN:True
a    Falseb     Truec    Falsed     Truedtype: bool
s.notnull()  # 检测每个元素,NOT NaN:True;NaN:False
a     Trueb    Falsec     Trued    Falsedtype: bool
s[s.notnull()]
a    2.0c    6.0dtype: float64

Series之间的运算

  • 在运算中自动对齐不同索引的数据
  • 如果索引不对应,则补NaN

DataFrame

DataFrame是一个【表格型】的数据结构。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。

  • 行索引:index
  • 列索引:columns
  • 值:values

DataFrame的创建

最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一列的名称,以字典的值(一个数组)作为每一列。

此外,DataFrame会自动加上每一行的索引。

使用字典创建的DataFrame后,则columns参数将不可被使用。

同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。

  • 使用ndarray创建DataFrame
df = DataFrame(data=np.random.randint(0,100,size=(3,4)),index=[‘a‘,‘b‘,‘c‘],columns=[‘A‘,‘B‘,‘C‘,‘D‘])df
A B C D
a 49 10 86 64
b 6 74 62 13
c 49 79 14 25

DataFrame属性:values、columns、index、shape

df.values
array([[49, 10, 86, 64],       [ 6, 74, 62, 13],       [49, 79, 14, 25]])
df.columns
Index([‘A‘, ‘B‘, ‘C‘, ‘D‘], dtype=‘object‘)
df.index
Index([‘a‘, ‘b‘, ‘c‘], dtype=‘object‘)
df.shape
(3, 4)

试做:使用ndarray创建DataFrame:创建一个表格用于展示张三,李四,王五的java,python的成绩

dic = {    ‘张三‘:[150,150,150,150],    ‘李四‘:[0,0,0,0]}df = DataFrame(data=dic,index=[‘语文‘,‘数学‘,‘英语‘,‘理综‘])df
张三 李四
语文 150 0
数学 150 0
英语 150 0
理综 150 0

DataFrame的索引

(1) 对列进行索引

- 通过类似字典的方式  df[‘q‘]- 通过属性的方式     df.q

可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。

df
张三 李四
语文 150 0
数学 150 0
英语 150 0
理综 150 0
# 修改列索引df[‘张三‘]   # 返回的是Series
语文    150数学    150英语    150理综    150Name: 张三, dtype: int64
# 获取前两列df[[‘李四‘,‘张三‘]]
李四 张三
语文 0 150
数学 0 150
英语 0 150
理综 0 150

(2) 对行进行索引

- 使用.loc[]加index来进行行索引- 使用.iloc[]加整数来进行行索引

同样返回一个Series,index为原来的columns。

df.loc[‘语文‘]
张三    150李四      0Name: 语文, dtype: int64
df.iloc[0]
张三    150李四      0Name: 语文, dtype: int64
df.iloc[[0,1]]
张三 李四
语文 150 0
数学 150 0

(3) 对元素索引的方法
- 使用列索引
- 使用行索引(iloc[3,1] or loc[‘C‘,‘q‘]) 行索引在前,列索引在后

df[‘张三‘][‘英语‘]
150
df.loc[‘英语‘,‘张三‘]  # 逗号左方:行,右方:列
150
df.loc[[‘数学‘,‘理综‘],‘张三‘]  # 逗号左方:行,右方:列
数学    150理综    150Name: 张三, dtype: int64

切片:

【注意】
直接用中括号时:

  • 索引表示的是列索引
  • 切片表示的是行切片
df
张三 李四
语文 150 0
数学 150 0
英语 150 0
理综 150 0
df[0:2]
张三 李四
语文 150 0
数学 150 0

在loc和iloc中使用切片(切列) : df.loc[‘B‘:‘C‘,‘丙‘:‘丁‘]

df.iloc[:,0:1]
张三
语文 150
数学 150
英语 150
理综 150

索引:

  • df[列索引]:取一列
  • df[[col1,col2]]:取出两列
  • df.loc[显示的行索引]:取行
  • df.loc[行,列]:取元素
    切片:
  • df[index1:index3]:切行
  • df.loc[col1:col3]:切列

3)DataFrame的运算

(1) DataFrame之间的运算

同Series一样:

  • 在运算中自动对齐不同索引的数据
  • 如果索引不对应,则补NaN

创建DataFrame df1 不同人员的各科目成绩,月考一

创建DataFrame df2 不同人员的各科目成绩,月考二
有新学生转入

============================================练习6:1. 假设ddd是期中考试成绩,ddd2是期末考试成绩,请自由创建ddd2,并将其与ddd相加,求期中期末平均值。2. 假设张三期中考试数学被发现作弊,要记为0分,如何实现?3. 李四因为举报张三作弊立功,期中考试所有科目加100分,如何实现?4. 后来老师发现有一道题出错了,为了安抚学生情绪,给每位学生每个科目都加10分,如何实现?============================================
qizhong = dfqimo = df
(qizhong + qimo)/2
张三 李四
语文 150.0 0.0
数学 150.0 0.0
英语 150.0 0.0
理综 150.0 0.0
qizhong.loc[‘数学‘,‘张三‘] = 0qizhong
张三 李四
语文 150 0
数学 0 0
英语 150 0
理综 150 0
qizhong[‘李四‘] += 100qizhong
张三 李四
语文 150 100
数学 150 100
英语 150 100
理综 150 100
qizhong += 10qizhong
张三 李四
语文 160 110
数学 160 110
英语 160 110
理综 160 110

股票项目

https://www.joinquant.com/

tushare官网tushare.orghttps://tushare.pro/

  • 使用tushare包获取某股票的历史行情数据。
import tushare as tsdf = ts.get_k_data(‘600519‘,start=‘2020-08-10‘)
df.to_csv(‘./maotai.csv‘) # 持久化储存
df = pd.read_csv(‘./maotai.csv‘)df
Unnamed: 0 date open close high low volume code
0 0 2020-08-10 1627.97 1633.99 1644.96 1608.11 23624.0 600519
1 1 2020-08-11 1640.00 1642.51 1666.43 1640.00 35818.0 600519
2 2 2020-08-12 1633.00 1626.95 1641.00 1605.25 27934.0 600519
3 3 2020-08-13 1630.00 1635.00 1638.88 1609.00 20541.0 600519
4 4 2020-08-14 1639.90 1661.00 1665.70 1631.00 37653.0 600519
df.drop(labels=‘Unnamed: 0‘,axis=1,inplace=True)# drop函数中0是行。删除行,inplace=True:在原数据中删除。
# 验证data列中数据的数据类型type(df[‘date‘][2])  # str
df.head(2)
date open close high low volume code
0 2020-08-10 1627.97 1633.99 1644.96 1608.11 23624.0 600519
1 2020-08-11 1640.00 1642.51 1666.43 1640.00 35818.0 600519
# 将date这一列的数据转成时间类型然后将其作为原数据的行索引df = pd.read_csv(‘./maotai.csv‘,index_col=‘date‘,parse_dates=[‘date‘])# index_col:将列转为行索引,parse_dates:设置为时间类型df.drop(labels=‘Unnamed: 0‘,axis=1,inplace=True)df
open close high low volume code
date
2020-08-10 1627.97 1633.99 1644.96 1608.11 23624.0 600519
2020-08-11 1640.00 1642.51 1666.43 1640.00 35818.0 600519
2020-08-12 1633.00 1626.95 1641.00 1605.25 27934.0 600519
2020-08-13 1630.00 1635.00 1638.88 1609.00 20541.0 600519
2020-08-14 1639.90 1661.00 1665.70 1631.00 37653.0 600519

输出该股票所有收盘比开盘上涨1%以上的日期

#(收盘-开盘)/开盘 > 0.01(df[‘close‘] - df[‘open‘]) / df[‘open‘] > 0.01#True:满足需求#false:不满足
date2020-08-10    False2020-08-11    False2020-08-12    False2020-08-13    False2020-08-14     Truedtype: bool
#返回了满足需求的行数据df.loc[(df[‘close‘] - df[‘open‘]) / df[‘open‘] > 0.01]
open close high low volume code
date
2020-08-14 1639.9 1661.0 1665.7 1631.0 37653.0 600519
#获取了满足需求的日期df.loc[(df[‘close‘] - df[‘open‘]) / df[‘open‘] > 0.01].index# 结论:如果获取了一组布尔值,接下来改组布尔值就直接作为元数据的行索引
DatetimeIndex([‘2020-08-14‘], dtype=‘datetime64[ns]‘, name=‘date‘, freq=None)
  • 输出该股票所有开盘比前日收盘跌幅超过2%的日期。
  • (开盘-前日收盘)/ 前日收盘 < -0.02
# (df[‘open‘] - df[‘close‘].shift(1))/df[‘close‘].shift(1) < -0.02# df[‘close‘].shift(1):将close一列下移一列#满足需求的行数据df.loc[(df[‘open‘] - df[‘close‘].shift(1))/df[‘close‘].shift(1) < -0.02].index
  • 假如我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到19年9月为止,我的收益如何?
  • 分析:
    • 规则:基于开盘价股票的买卖
    • 买:一个完整的年需要买12次股票,一次买入100只,一个完整的年需要买入1200只(单价:当天开盘价)
    • 卖:一个完整的年需要卖一次股票,一次卖出1200只
    • 备注:19年不是一个完整的年,该年只可以买入900只,并且卖不出去
df_new = df[‘2010‘:‘2019‘]  # 切片,[‘2010-01‘:‘2019-09‘]也可以# 数据的重新取样的机制(resample):根据指定好的规则进行指定数据的提取df_monthly = df_new.resample(‘M‘).first() # 年:A,月:M
# 计算出买股票一共花了多少钱cost_monry = df_monthly[‘open‘].sum()*100cost_monry
  • 卖出所有的股票一共进账多少钱
    • 每年最后一个交易日以开盘价为单价进行卖出
df_yearly = df_new.resample(‘A‘).last()df_yearly = df_yearly[:-1]
recv_monry = df_yearly[‘open‘].sum()*1200
  • 19年买入了900只股票没有卖出,剩余的股票也计算到总收益
    • 剩余股票的单价应该选择使用昨日的收盘价
last_price = df.iloc[-1][‘close‘]
cunHuo_price = last_price * 900
#计算总收益cunHuo_price+recv_monry-cost_monry # 528908.7

处理丢失数据

有两种丢失数据:

  • None
  • np.nan(NaN)

None是Python自带的,其类型为python object。因此,None不能参与到任何计算中。

np.nan(NaN)是浮点类型,能参与到计算中。但计算的结果总是NaN。

pandas中None与np.nan都视作np.nan

pandas处理空值操作

  • isnull()
  • notnull()
  • dropna(): 过滤丢失数据
  • fillna(): 填充丢失数据

创建DataFrame,给其中某些元素赋值为nan

(1)判断函数

  • isnull()

  • notnull()

  • df.notnull/isnull().any()/all()

过滤df中的空值(只保留没有空值的行)

df.dropna() 可以选择过滤的是行还是列(默认为行):axis中0表示行,1表示的列

(3) 填充函数 Series/DataFrame

  • fillna():value和method参数。

可以选择前向填充还是后向填充。

method 控制填充的方式 bfill ffill

练习7:1. 简述None与NaN的区别2. 假设张三李四参加模拟考试,但张三因为突然想明白人生放弃了英语考试,因此记为None,请据此创建一个DataFrame,命名为ddd33. 老师决定根据用数学的分数填充张三的英语成绩,如何实现?    用李四的英语成绩填充张三的英语成绩?

相关推荐