#导入相应模块
import re
import os
import pandas as pd
import numpy as np
# 读取 10个csv 文件
path = 'E:/round1/'
files = os.listdir(path)
files_csv = list(filter(lambda x: x[-4:]=='.csv' , files))
#定义一个空列表
data_list = []
#函数re.compile将正则表达式(以字符串书写的)转换为模式对象
num_filter = re.compile(r'\d+')
通过help可以看到compile方法的介绍,返回一个pattern对象,但是却没有对第二个参数flags进行介绍。第二个参数flags是匹配模式,可以使用按位或'|'表示同时生效,也可以在正则表达式字符串中指定。Pattern对象是不能直接实例化的,只能通过compile方法得到。匹配模式有:
1).re.I(re.IGNORECASE): 忽略大小写
2).re.M(MULTILINE): 多行模式,改变'^'和'$'的行为
3).re.S(DOTALL): 点任意匹配模式,改变'.'的行为
4).re.L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
5).re.U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
6).re.X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。
# 循环读取文件中‘code','close'两列,并添加一列'rank'
for file in files_csv:
tmp = pd.read_csv(path + file)[['code', 'close']]
tmp['rank'] = num_filter.findall(file)[0]
data_list.append(tmp)
# 将读入的数据连接
all_data = pd.concat(data_list)
all_data.head()
根据运行结果,可以看出我们所添加的那一列的数值是根据所连接的列表的filename有关系的。
tmp['rank'] = num_filter.findall(file)[0],就是说添加的这一列的“rank”就等于所读入的file的name.
# 将‘rank'一列数据赋值给all_data_rank all_data_rank = pd.to_numeric(all_data['rank']) all_data.dtypes
为了方便后面的排序,我们先查看一下数据的类型,由结果可以看出,rank一列的数据是object型的,所以我们就用到pd.to_numeric。 对于明显是数值的数据,转换类型直接采用 pd.to_numeric 。
# 删除'rank'一列
all_data = all_data.drop('rank', axis = 1)
# 在0列插入一列'rank'值为all_data_rank的值
all_data.insert(0, 'rank', all_data_rank)
# 将数据按照'code','rank'的值排序
a = all_data.sort_values(by = ['code','rank'])
# 取code 的唯一值,并求其长度
len(a.code.unique()) # 长度为737
code = a.code.unique()
# 重复十遍,并生成列表
code = code.repeat(10)
code = code.tolist()
# 循环1~10,并重复循环737次,生成列表
x = np.arange(1,11, step = 1)
y=np.tile(x,737)
y = y.tolist()
用repeat和tile扩充数组元素,例如,
In [32]: a=np.arange(10)
In [33]: a
Out[33]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [34]: a.repeat(5)
Out[34]:
array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4,
4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9,
9, 9, 9, 9])
In [40]: np.tile(a,2)
Out[40]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [32]: a=np.arange(10)
In [33]: a
Out[33]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [34]: a.repeat(5)
Out[34]:
array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4,
4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9,
9, 9, 9, 9])
In [40]: np.tile(a,2)
Out[40]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 以生成的两个列表生成新的数据框
y = pd.DataFrame({'rank': y,'code': code})
y.head()
# 将数据框和新生成的数据框左连接
b = pd.merge(y, a, how='left')
sum(b.isnull().values)# 查看数据框的缺失值
array([ 0, 0, 153])
# 将数据根据“code”进行分组
group_rank = b.groupby(['code'])
# 分别向前先后填充缺失值
d = b.fillna(method = 'bfill',limit = 3) #用limit限制每列可以替代NaN的数目
d = d.fillna(method = 'ffill')
sum(d.isnull().values)
当数据中存在NaN缺失值时,我们可以用其他数值替代NaN,主要用到了DataFrame.fillna()方法,
使用0替代缺失值(当然你可以用任意一个数字代替NaN);
df.fillna(0)
用一个字符串代替缺失值;
df.fillna('missing')
用前一个数据代替NaN:method='pad'或者 method='ffill';
df.fillna(method='pad')
与pad相反,bfill表示用后一个数据代替NaN;df.fillna(method='pad')
这里我们增加一个知识点,用limit限制每列可以替代NaN的数目;
df.fillna(method='bfill',limit=1)
除了上面用一个具体的值来代替NaN之外,还可以使用平均数或者其他描述性统计量来代替NaN;
df.fillna(df.mean()