Pandas

Pandas的数据结构

导入pandas:

import pandas as pd
from pandas import Series,DataFrame
import 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的整数型索引
# 使用列表创建Series
Series(data=[1,2,3,])
0    1
1    2
2    3
dtype: int64
Series(data=np.random.randint(0,100,size=(3)))
0    93
1    76
2    65
dtype: int32
  • 可以通过设置index参数指定索引
Series(data=[1,2,3],index=['a','b','c']) #显式索引
a    1
b    2
c    3
dtype: 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    1
b    2
c    3
d    4
dtype: int64
s[1]  # 2,隐式索引:
s['a']  # 1
s.a  # 1  显示索引

隐式索引:

  • 使用整数作为索引值

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

    注意,此时是半开区间

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

Series的基本概念

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

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

对Series元素进行去重

s = Series([1,1,1,2,3,3,3,3,2])
s.unique()
array([123], 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 + s2
s
a    2.0
b    NaN
c    6.0
d    NaN
dtypefloat64

可以使用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.0
c    6.0
dtypefloat64
s.isnull()   # 检测每个元素,NOT NaN:False;NaN:True
a    False
b     True
c    False
d     True
dtype: bool
s.notnull()  # 检测每个元素,NOT NaN:True;NaN:False
a     True
b    False
c     True
d    False
dtype: bool
s[s.notnull()]
a    2.0
c    6.0
dtypefloat64

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
理综    150
Name: 张三, dtype: int64
# 获取前两列
df[['李四','张三']]
李四 张三
语文 0 150
数学 0 150
英语 0 150
理综 0 150

(2) 对行进行索引

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

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

df.loc['语文']
张三    150
李四      0
Name: 语文, dtype: int64
df.iloc[0]
张三    150
李四      0
Name: 语文, 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
理综    150
Name: 张三, 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 = df
qimo = df
(qizhong + qimo)/2
张三 李四
语文 150.0 0.0
数学 150.0 0.0
英语 150.0 0.0
理综 150.0 0.0
qizhong.loc['数学','张三'] = 0
qizhong
张三 李四
语文 150 0
数学 0 0
英语 150 0
理综 150 0
qizhong['李四'] += 100
qizhong
张三 李四
语文 150 100
数学 150 100
英语 150 100
理综 150 100
qizhong += 10
qizhong
张三 李四
语文 160 110
数学 160 110
英语 160 110
理综 160 110

股票项目

https://www.joinquant.com/

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

  • 使用tushare包获取某股票的历史行情数据。
import tushare as ts
df = 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:不满足
date
2020-08-10    False
2020-08-11    False
2020-08-12    False
2020-08-13    False
2020-08-14     True
dtype: 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()*100
cost_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,命名为ddd3

3. 老师决定根据用数学的分数填充张三的英语成绩,如何实现?
    用李四的英语成绩填充张三的英语成绩?
posted @ 2020-08-15 23:37  虫萧  阅读(170)  评论(0编辑  收藏  举报