Python中pandas和numpy的使用(更新ing)

By | 2019年5月19日

目录:

  1. 对行操作
  2. 对列操作
  3. 对单个dataframe操作
  4. 对多个dataframe操作
  5. numpy-对单个数组array操作

1.对行操作

目录:

  • 1.1 选择行

1.1 选择行

df[10:21]       # 选择第10-20行,index为数字

2.对列操作

目录:

  • 2.1取一列最大值、最小值、平均值

2.1取一列最大值、最小值、平均值

df['close'].max()                # 最大值
df['close'].min()                # 最小值
df['close'].mean()               # 平均值

3.对单个dataframe操作

目录:

  • 3.1初始化dataframe
  • 3.2作为dataframe读取文件
  • 3.3去掉dataframe中某些值
  • 3.4切片(选取某些行、列)
  • 3.5取出dataframe中的数值
  • 3.6计算dataframe的统计值
  • 3.7对dataframe加减乘除

3.1初始化dataframe

start_date = '2010-01-22'
end_date = '2010-01-26'
dates = pd.date_range(start_date, end_date)
df = pd.DataFrame(index=dates)    # 使用index参数,指定日期作为索引

3.2作为dataframe读取文件

read_csv函数用来读取csv文件,官方文档

# 直接读取文件,索引值为整数0、1、2……
df = pd.read_csv('data.csv')

# 将日期这一列以datetime形式作为索引
df = pd.read_csv('data.csv', index_col='date', parse_dates=True)

# 只获取文件中的某些列
df = pd.read_csv('data/SPY.csv', index_col='date', parse_dates=True, usecols=['date', 'close'], na_values=['nan'])

# 读取多个文件
symbols = ['Google', 'IBM', 'GLD']
for symbol in symbols:
    df_temp = pd.read_csv('data/{}.csv'.format(symbol), index_col='date', parse_dates=True, usecols=['date', 'close'], na_values=['nan'])
    # 不加下面这句就会报错,因为每个文件的列名都叫close,导致混淆
    df_temp = df_temp.rename(columns={'close': symbol})
    df = df.join(df_temp)            # 默认how='left',df为前面非空dataframe

可以写一个复用函数读取数据

import os
def symbol_to_path(symbol, base_dir='data'):
    # 根据股票代码字符串,返回对应的csv文件路径
    return os.path.join(base_dir, '{}.csv'.format(str(symbol)))

df_temp = pd.read_csv(symbol_to_path(symbol), index_col='date', parse_dates=True, usecols=['date', 'close'], na_values=['nan'])

3.3去掉dataframe中某些值

3.3.1去掉NaN

df = df.dropna()

# 去掉 close 这一列为NaN的行
df = df.dropna(subset=['close'])

3.4切片(选取某些行、列)

设定索引和选择数据,官方文档

3.4.1行切片

# 如果去掉 ix,得到的结果是一样的,但是ix更稳定,所以一般都加上 ix
df_subset = df.ix['2010-01-01':'2010-01-31']

# 只取一行
df_subset = df[0]
# 或者
df_subset = df.ix[0]
# 或者
df_subset = df.ix[0, :]

3.4.2列切片

# 选择一列
df_subset = df['Google']      # Google为列名

# 选择多列
df_subset = df[['Google', 'IBM']]

3.4.3行列切片

# 取出某些行的某些列
df_subset = df.ix['2010-03-10':'2010-03-15', ['SPY', 'Google', 'IBM']]

3.5取出dataframe中的数值

通过numpy进行切片,官方文档

# 将dataframe中的所有数取出作为一个数组
a =get_price_change_rate(['000001.XSHE', '000300.XSHG'], '20150801', '20150807')
print(a)
nd1 = a.values
print(nd1)
print(nd1[3, 1])
print(nd1[1:3, 0:1])

order_book_id  000001.XSHE  000300.XSHG
date                                   
2015-08-03        0.037217     0.003285
2015-08-04        0.003120     0.031056
2015-08-05       -0.020995    -0.020581
2015-08-06       -0.004766    -0.009064
2015-08-07        0.006385     0.019597
[[ 0.03721685  0.00328454]
 [ 0.00312016  0.03105581]
 [-0.02099537 -0.02058065]
 [-0.00476569 -0.00906364]
 [ 0.00638464  0.01959711]]
-0.009063643179996639
[[ 0.00312016]
 [-0.02099537]]

3.6计算dataframe的统计值

3.6.1全局统计量

类似下面的形式,pandas可以计算至少33种全局性统计量。

df.mean()              # 每一列的平均值
df.median()            # 中位数
df.mode()              # 众数
df.std()               # 标准差,方差的平方根
df.sum()               # 每一列的和
df.sum(axis=1)         # 每一行的和
df.prod()              # 每一列的累乘

# 计算一行数据的和,并作为新列添加到末尾
df['Col_sum'] = df.apply(lambda x: x.sum(), axis=1)
# 计算一列数据的和,并作为新行添加到末尾
df.loc['Row_sum'] = df.apply(lambda x: x.sum())

下面这个函数,可以列出Dataframe中各列的统计指标,指标有count、mean、std、min、25%、50%、75%、max等。

df.describe()
Python求标准差std
  1. numpy.std() 求标准差时默认是除以 n 的,即是有偏的,如果希望求无偏的,则加入参数 ddof = 1,即np.std(a, ddof = 1);
  2. pandas.std() 求标准差时默认是除以 n-1 的,即是无偏的,如果希望求有偏的,则加入参数 ddof = 0;

3.6.2rolling统计量

假设窗口为20天,取20天交易日的平均值,然后将窗口向后移动一天后再取另一个平均值,那么一年中每移动一天就取一个平均值,这就叫做 滚动平均值(rolling mean)。

这被分析师称为简单移动平均,而分析师要观察的其中一项就是价格和滚动平均值相交的位置。有一个假说:滚动平均值可能在某种程度上代表了一只股票真正的潜在价格,而那些股票价格偏离滚动平均值的点最终会回到平均值。所以如果能找到大幅偏离均值的点,你可能找到了一个买入/卖出的机会。但如何知道什么时候这个偏差足够大,就是一个值得思考的问题了。(可以使用rolling 标准差,即布林带)

类似滚动平均值,我们可以计算其他滚动统计量。





3.7对dataframe加减乘除

df1/df2                      # 每一列除以对应的向量
df1.div(df2, axis='rows')    # 每一行除以对应的向量,比如df2为df1每一行的和

4.对多个dataframe操作

目录:

  • 4.1连接两个dataframe
  • 4.2多个dataframe加减乘除

4.1连接两个dataframe

4.1.1向左合并

如果写成 a.join(b),(官方文档),将保留a中所有行,但是只有既包含在a中也包含在b中的索引值才会合并,对于不存在b中的索引,会用 NaN 填充。

df1 = df1.join(dfSPY)     # join默认向左合并
df1 = df1.dropna()        # 删除NaN的行

以上操作可以通过how参数一步实现:

df1.join(dfSPY, how='inner')    # how:{‘left’, ‘right’, ‘outer’, ‘inner’}, 
                                # default ‘left’

4.2多个dataframe加减乘除

df1 * df2              # df1的行与df2的行逐元素相乘,最终结果和df1/df2大小一样

5.numpy-对单个数组array操作

目录:

  • 5.1初始化array
  • 5.2生成随机数
  • 5.3array的属性
  • 5.4访问/修改数组元素
  • 5.5加减乘除

5.1初始化array

# 创建一维数组,默认都是浮点数,加上 dtype=int或dtype=np.int_ 即可变成整数
a = np.array([2,3,4])      # 括号中可以是一个列表,也可以是元组,或其它序列
c = np.empty(5)            # 初始化一个随机数组
e = np.ones(5)             # 创建一个全1数组
f = np.zeros(5, dtype=int) # 创建一个全0数组

# 创建二维数组
b = np.array([(2,3,4), (5,6,7)])
d = np.empty((5,2))

print(a,b,c,d,e,f)

[2 3 4]
[[2 3 4]
 [5 6 7]]
[0.00328454 0.03105581 0.02058065 0.00906364 0.01959711]
[[0.03721685 0.00312016]
 [0.02099537 0.00476569]
 [0.00638464 0.00328454]
 [0.03105581 0.02058065]
 [0.00906364 0.01959711]]
[1. 1. 1. 1. 1.]
[0 0 0 0 0]

为什么我们调用了numpy.empty函数,输出的数组却并不是空呢?这是因为数组读出了存储于相应位置内存的值,实际上是随机值,不管这个值是什么,取决于计算机的内存状态。

5.2生成随机数

可以查看random官方文档

# 加上下面这句话,可以保证每次生成的随机数一样,括号里的值可以变
np.random.seed(693) 

a = np.random.random((5, 4))    # 产生[0,1)之间的浮点数
b = np.random.rand(5, 4)        # 两个函数作用相同
print(a)
[[0.93478364 0.47981225 0.44066942 0.35926848]
 [0.43888233 0.54151385 0.65543919 0.44834759]
 [0.90615702 0.60370222 0.17369364 0.16094041]
 [0.44154703 0.95414391 0.276216   0.68406815]
 [0.28438368 0.44906608 0.27844548 0.17576578]]

# 生成正态分布的随机数
c = np.random.normal(size=(3,2))   # 必须有size参数, mean=0, std=1
d = np.random.normal(50, 10, size=(3,2))   # mean=50, std=10

# 生成整数
a = np.random.randint(10)                  # [0,10)中的某个整数
b = np.random.randint(50, 100)             # [50,100)中的某个整数
c = np.random.randint(0, 10, size=5)       # 5个随机整数
d = np.random.randint(0, 10, size=(2, 3))  # 二维整数数组
print(a,b,c,d)

9
55
[4 9 3 0 5]
[[6 7 1]
 [6 4 8]]

random.uniform(x, y)            # 随机生成一个浮点数,在 [x,y) 范围内

5.3array的属性

5.3.1array的大小

a = np.random.random((5,4))
a.shape                          # 返回数组大小=(5,4)
a.shape[0]                       # 返回行数
a.shape[1]                       # 返回列数

len(a.shape)                     # 返回数组的维数=2

a.size                           # 返回数组元素的个数=5*4=20

a.dtype                          # 返回数组元素的类型=float64

5.3.2对array求和、最大、最小、平均

a = np.random.randint(0, 10, size=(5,4))
[[5 3 6 5]
 [3 2 6 8]
 [8 5 3 3]
 [1 4 0 1]
 [1 4 9 5]]

a.sum()                            # 返回数组所有元素的和=82

a.sum(axis=0)                      # 所有列的和
[18 18 24 22]

a.sum(axis=1)                      # 所有行的和
[19 19 19  6 19]

a.min()                            # 所有元素的最小值
a.min(axis=0)                      # 每一列的最小值
a.argmin()

a.max()                            # 所有元素的最大值
a.max(axis=1)                      # 每一行的最大值
a.argmax()                         # 所有元素中最大值的索引值

a.mean()                           # 所有元素的平均值
a.mean(axis=0)                     # 每一列的平均值

5.4访问/修改数组元素

array索引,indexing官方文档

5.4.1 访问数组元素

a = np.random.rand(5,4)
print(a)
print(a[1:3, 0:3])                        # 切片
print(a[1:3, 0:3:2])                      # 2 表示间隔切片

[[0.05670466 0.78607025 0.67588477 0.57220884]
 [0.10019578 0.41069294 0.08127206 0.61096265]
 [0.1365505  0.75357939 0.78051369 0.9068128 ]
 [0.65116998 0.66966774 0.38017339 0.81585731]
 [0.92632699 0.58018401 0.13991508 0.36258477]]
[[0.10019578 0.41069294 0.08127206]
 [0.1365505  0.75357939 0.78051369]]
[[0.10019578 0.08127206]
 [0.1365505  0.78051369]]

通过索引列表访问,官方文档

a = np.random.randint(0, 100, size=5)
print(a)
# 下面也可以写成 indices = [1,1,3,2]
indices = np.array([1,1,3,2])             
print(a[indices])

[48 80 76 39 33]
[80 80 39 76]

通过条件获取元素,masking 操作

表达式 a<a.mean() 会生成一个布尔型数组,使用该数组对数组a设定索引时,只有值为True的位置才会选中,并且这些值将添加到列表中。

a = np.random.randint(0, 100, size=10)
print(a)
print(a[a<a.mean()])                     # 输出所有小于均值的元素   
a[a<a.mean()] = a.mean()                 # 修改所有小于均值的元素
print(a)

[ 7 60 24 21 23 56 86 83 67 23]
[ 7 24 21 23 23]
[45 60 45 45 45 56 86 83 67 45]

5.4.2 修改数组元素

a[0, 0] = 1                  # 修改某个值
a[0, :] = 2                  # 修改整行的值为一个相同的值
a[:, 3] = [1,2,3,4,5]        # 修改整列的值为一个列表

5.5加减乘除

a = np.random.randint(0, 100, size=10)
b = np.random.randint(0, 100, size=10)
print(a*2)
print(a/2)
print(a/2.0)
print(a+b)
print(a*b)                           # 逐元素进行的乘法

参考文献:

  1. NumPy 用户指南
  2. NumPy 参考文档

发表评论

电子邮件地址不会被公开。 必填项已用*标注