数据有各种大小、格式和编码。如果要有效地处理数据,通常需要处理并转换为一种常用的格式,以便高效处理、排序和存储。
一、分解数据
为不同的文本数据分别创建一个列表,并在屏幕上显示列表。
# 打开文件
with open('james.txt') as jaf:
# 读数据行
data=jaf.readline()
# 将数据转换为一个列表
james=data.strip().split(',')
# 方法串链。去除字符串中所有空白符后,处理并创建新列表。
with open('julie.txt') as juf:
data=juf.readline()
julie=data.strip().split(',')
with open('mikey.txt') as mif:
data=mif.readline()
mikey=data.strip().split(',')
with open('sarah.txt') as saf:
data=saf.readline()
sarah=data.strip().split(',')
# 显示列表
print(james)
print(julie)
print(mikey)
print(sarah)
二、数据排序
1、原地排序
按指定的顺序排列数据,然后用排序后的数据替换原来的数据,原来的顺序会丢失。
对于列表,sort( )方法会提供原地排序。
# 创建一个无序数据的列表,赋至一个变量
data=[6,3,1,2,4,5]
# 原地排序
data.sort()
print(data)
2、复制排序
按指定的顺序排列数据,返回原数据的一个有序副本。原数据的顺序依然保留,只是对一个副本排序。sorted( )支持复制排序。
# 创建一个无序数据的列表,赋至一个变量
data2=[6,3,1,2,4,5]
# 复制排序
a=sorted(data2)
print(a)
print(data2)
3、对数据进行复制排序
# 对数据使用复制排序
with open('james.txt') as jaf:
data=jaf.readline()
james=data.strip().split(',')
with open('julie.txt') as juf:
data=juf.readline()
julie=data.strip().split(',')
with open('mikey.txt') as mif:
data=mif.readline()
mikey=data.strip().split(',')
with open('sarah.txt') as saf:
data=saf.readline()
sarah=data.strip().split(',')
print(sorted(james))
print(sorted(julie))
print(sorted(mikey))
print(sorted(sarah))
可见数据排序出错。数据中存在的不一致性导致排序失败。
三、清理数据
# 创建一个函数,从各列表接受一个字符串作为输入
# 然后处理这个字符串,将找到的所有短横线或冒号替换为一个点号
# 返回清理过的字符串(如果字符串已经包含一个点号,则不需要再清理)
def sanitize(time_string):
# 使用in操作符检查字符串是否包含一个短横线或冒号
if '-' in time_string:
splitter='-'
elif ':' in time_string:
splitter=':'
else:
return(time_string)
# 如果字符串不需要清理,就什么也不做
(min,secs)=time_string.split(splitter)
# 分解字符串
return(min+'.'+secs)
# 迭代处理每一个数据列表
with open('james.txt') as jaf:
data=jaf.readline()
james=data.strip().split(',')
with open('julie.txt') as juf:
data=juf.readline()
julie=data.strip().split(',')
with open('mikey.txt') as mif:
data=mif.readline()
mikey=data.strip().split(',')
with open('sarah.txt') as saf:
data=saf.readline()
sarah=data.strip().split(',')
# 创建空的新列表
clean_james=[]
clean_julie=[]
clean_mikey=[]
clean_sarah=[]
# 取原列表中的各个数据项进行清理,追加到新列表
for each_t in james:
clean_james.append(sanitize(each_t))
for each_t in julie:
clean_julie.append(sanitize(each_t))
for each_t in mikey:
clean_mikey.append(sanitize(each_t))
for each_t in sarah:
clean_sarah.append(sanitize(each_t))
# 显示已排序的新列表
print(sorted(clean_james))
print(sorted(clean_julie))
print(sorted(clean_mikey))
print(sorted(clean_sarah))
默认地,sort( )方法与sorted( )BIF都会按升序对数据进行排序。要以降序排序,则需要向sort( )或sorted( )传入参数reverse=True。
四、推导列表
设计列表推导是为了减少将一个列表转换为另一个列表时所需编写的代码量。
1、列表推导
# 创建一个新列表来存放转换后的数据
clean_mikey=[]
# 迭代处理原列表中的各个数据项
for each_t in mikey:
# 每次迭代时完成转换
# 将转换后的数据追加到新列表
clean_mikey.append(sanitize(each_t))
# 转换为以下代码
clean_mikey=[sanitize(each_t) for each_t in mikey]
# 不需要append()方法,因为这个动作已经隐含在列表推导中
2、列表推导的栗子
# 分钟转换为秒
mins=[1,2,3]
secs=[m*60 for m in mins]
print(secs)
# 米转换为英尺
meters=[1,10,3]
feet=[m*3.281 for m in meters]
print(feet)
# 给定包含混合大小写字符串的列表,转换为全大写的字符串
lower=['I',"don't",'like','spam']
upper=[s.upper() for s in lower]
print(upper)
# sanitize()函数
dirty=['2-22','2:22','2.22']
clean=[sanitize(t) for t in dirty]
print(clean)
# 将一个字符串列表转换为一个浮点数列表,替换原来的列表数据
clean=[float(s) for s in clean]
print(clean)
# 转换还可以是一个函数链
# 支持合并对数据项的转换
clean=[float(sanitize(t)) for t in ['2-22','3:33','4.44']]
print(clean)
# 列表推导与列表迭代
# 如果必须对一个列表中的每一项完成一个转换,使用列表推导是上策
# 特别是如果能很容易地在一行上指定转换(或指定为一个函数链),列表推导尤其适用
# 列表迭代可以完成列表推导所能完成的全部工作,只是代码量多一些
# 但迭代确实能提供更大的灵活性
3、使用列表推导
def sanitize(time_string):
if '-' in time_string:
splitter='-'
elif ':' in time_string:
splitter=':'
else:
return(time_string)
(min,secs)=time_string.split(splitter)
return(min+'.'+secs)
with open('james.txt') as jaf:
data=jaf.readline()
james=data.strip().split(',')
with open('julie.txt') as juf:
data=juf.readline()
julie=data.strip().split(',')
with open('mikey.txt') as mif:
data=mif.readline()
mikey=data.strip().split(',')
with open('sarah.txt') as saf:
data=saf.readline()
sarah=data.strip().split(',')
print(sorted([sanitize(t) for t in james]))
print(sorted([sanitize(t) for t in julie]))
print(sorted([sanitize(t) for t in mikey]))
print(sorted([sanitize(t) for t in sarah]))
# 定义列表推导时,千万别使用函数链sort(sanitize(t))。
# 这个栗子,sorted()BIF希望对一个系列表排序,而不是针对单个数据项
五、删除重复项
1、用迭代删除重复项
重复项的删除不是一个转换,更应算是一个过滤器。重复项删除过滤器需要在列表创建过程中检查所创建的列表,而列表推导无法做到。
with open('james.txt') as jaf:
data=jaf.readline()
james=data.strip().split(',')
with open('julie.txt') as juf:
data=juf.readline()
julie=data.strip().split(',')
with open('mikey.txt') as mif:
data=mif.readline()
mikey=data.strip().split(',')
with open('sarah.txt') as saf:
data=saf.readline()
sarah=data.strip().split(',')
# 排序和清理各个列表
james=sorted([sanitize(t) for t in james])
julie=sorted([sanitize(t) for t in julie])
mikey=sorted([sanitize(t) for t in mikey])
sarah=sorted([sanitize(t) for t in sarah])
# 删除重复的数据项
# 创建空列表存放唯一的数据项
unique_julie=[]
# 在现有的数据上迭代处理
for each_t in julie:
# 如果这个数据项还不在新列表中
if each_t not in unique_julie:
# 将这个唯一的数据项追加到新列表中
unique_julie.append(each_t)
# 从列表分片得到前三个数据项
print(unique_julie[0:3])
unique_julie=[]
for each_t in julie:
if each_t not in unique_julie:
unique_julie.append(each_t)
print(unique_julie[0:3])
unique_mikey=[]
for each_t in mikey:
if each_t not in unique_mikey:
unique_mikey.append(each_t)
print(unique_mikey[0:3])
unique_sarah=[]
for each_t in sarah:
if each_t not in unique_sarah:
unique_sarah.append(each_t)
print(unique_sarah[0:3])
2、用集合删除重复项
# python中集合最突出的特性是集合中的数据项是无序的,且不允许重复。
# 如果要向一个集合增加一个数据项,而集合中已经包含有这个数据项,则python会将其忽略。
# 使用set()BIF创建一个空集合,并赋至一个变量
distances=set()
# 也可以一步完成集合的创建和填充
# 可以在大括号之间提供一个数据列表,或指定一个现有列表作为set()BIF的参数,这就是工厂函数
distances={10.6,11,8,10.6,"two",7}
distances=set(james)
# 工厂函数:用于创建某种类型的新的数据项
# 例如,“set()”就是一个工厂函数,因为它会创建一个新的集合
工厂函数:用于创建某种类型的新的数据项 。
例如,“set()”就是一个工厂函数,因为它会创建一个新的集合。
with open('james.txt') as jaf:
data=jaf.readline()
james=data.strip().split(',')
with open('julie.txt') as juf:
data=juf.readline()
julie=data.strip().split(',')
with open('mikey.txt') as mif:
data=mif.readline()
mikey=data.strip().split(',')
with open('sarah.txt') as saf:
data=saf.readline()
sarah=data.strip().split(',')
将以上重复的代码抽取到一个小函数中,并调用这个函数
def sanitize(time_string):
if '-' in time_string:
splitter='-'
elif ':' in time_string:
splitter=':'
else:
return(time_string)
(mins,secs)=time_string.split(splitter)
return(mins+'.'+secs)
# 创建一个新函数,接受一个文件名作为唯一的参数
def get_coach_data(filename):
# 增加异常处理代码
try:
# 打开文件,读取数据
with open(filename) as f:
data=f.readline()
# 将数据返回到代码之前先对数据完成分解/去除空白符处理
return(data.strip().split(','))
except IOError as ioerr:
# 通知错误,并返回none指示失败
print('File error:'+str(ioerr))
return(None)
# 调用函数
james=get_coach_data('james.txt')
julie=get_coach_data('julie.txt')
mikey=get_coach_data('mikey.txt')
sarah=get_coach_data('sarah.txt')
# 对“sorted()”生成的列表应用分片
print(sorted(set([sanitize(t) for t in james]))[0:3])
print(sorted(set([sanitize(t) for t in julie]))[0:3])
print(sorted(set([sanitize(t) for t in mikey]))[0:3])
print(sorted(set([sanitize(t) for t in sarah]))[0:3])
第五章笔记:
# 1.原地排序——转换然后替换
# 复制排序——转换然后返回
# 方法串链——从左向右读,对数据应用一组方法
# 函数串链——从右向左读,对数据应用一组函数
# 列表推导——在一行上制定一个转换(非迭代)
# 分片——从一个列表访问多个列表项
# 集合——一组无序的数据项,其中不包含重复项
# 2.sort()方法可以在原地改变列表的顺序
# sorted()BIF通过提供复制排序可以对几乎任何话数据结构排序
# 3.向sort()或sorted()传入reverse=True可以按降序排列数据
# 对以下代码:
# new_l=[]
# for t in old_l:
# new_l.append(len(t))
# 使用列表推导重写这个代码:
# new_l=[len(t) for t in old_l]
# 4.要访问一个列表中的多个数据项,可以使用分片:
# 例如: my_list[3:6]
# 这会访问列表中从索引位置3直到(但不包括)索引位置6的列表项。
# 5.使用set()工厂方法可以创建一个集合。