天天看点

cp5_2_1.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : cp5_2_1.py
# @Author: WRH
# @Date  : 2021/4/12
# @Edition:Python3.8.6

# 5.3基于文件的数据分析
'''
基于文件的数据分析,通常是利用Python对文本文件操作的便利性,读取文本文件,并转换为相应的数据列表,
再利用循环结构实现统计分析。
'''

# 例5-7 根据考试成绩,统计学科等级水平。学生成绩原始数据查看score.txt文件。
# 编程要求:从score.txt文件中读取学生成绩数据,判定等级并写入level.txt文件中。
'''
学科等级水平统计标准如下:
(1)每门课达到85分,总分达到260分为优秀;
(2)生物和科学两门课都达到60分,总分达到180分为及格;
(3)总分不到180分或有任意一门课不到60分,为不及格。
'''

'''
程序实现方案一:
(1)读取文件score.txt数据到列表L中
列表L中的数据项对应着文件中的每条学生记录,通过循环语句遍历L,提取需要的考号和三门课的成绩,并存放在列表x中。
(2)判定学科等级
列表x包含4个数据项,x[0]为考号,x[1]、x[2]和x[3]分别为“程序设计”、“生物”和“科学”三门课的成绩,
需要转换为整数类型以便进行求和等数值运算。最后通过分支语句,将求得的等级结果存放在key变量中。
(3)将考号和等级结果按一定格式写入文件level.txt中。
代码如下:
'''
L = list(open('score.txt')) # 使用快速列表方式读取score.txt文件,并赋值为L
#print(L) # 在编程过程中,如果对数据类型和结构不明确,可以用print()将其打印出来,便于清晰直观的观察,下同
f = open('level.txt', 'w') # 使用w模式创建level.txt文件并打开写入,并赋值为f
del L[0] # 删除列表L中第0个元素,即score.txt文件中的第一行  (为标题内容,不是计算的对象)
for s in L:
    x = s.split() # split()通过指定分隔符对字符串进行切片,分隔符默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等
    #print(x)
    #print(len(x))
    for i in range(1, len(x)):
         x[i] = int(x[i]) # 将数据从字符转化成整数
    sum = x[1]+x[2]+x[3]
    if x[1] >= 85 and x[2] >= 85 and x[3] >= 85 and sum >= 260:
        key = '优秀'
    elif x[2] >= 60 and x[3] >= 60 and sum >= 180:
        key = '及格'
    else:
        key = '不及格'
    f.write('%s\t%s\n' % (x[0], key))
f.close()

'''程序实现方案二:
方案一利用列表存放文件中的数据,需要占用额外的内存空间。
更优的处理方法是使用readline()语句读取文件score.txt中的学生记录,对每条记录,判定该学生考核等级,
并与考号合并写入文件level.txt中。若某次循环读到空行,则跳出循环,结束对文件的处理。
'''
s = open('score.txt') # 使用默认r模式打开score.txt文件,并赋值为s
f = open('level.txt', 'w') # 使用w模式创建level.txt文件并打开写入,并赋值为f
s.readline() # 读取第一行标题,指针移到第二行开头,此语句避免标题行内容进入循环,引起错误
while True:
    x = s.readline().split() # split()通过指定分隔符对字符串进行切片,分隔符默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等
    #print(x)
    if len(x) == 0: # 如果已到达文件的末尾,f.readline()将返回一个空字符串(''),此语句避免末尾空列表进入判断语句引起错误
        break
    for i in range(1, len(x)):
        x[i] = int(x[i])
    sum = x[1]+x[2]+x[3]
    if x[1] >= 85 and x[2] >= 85 and x[3] >= 85 and sum >= 260:
        f.write('%s\t%s\n' % (x[0], '优秀'))
    elif x[2] >= 60 and x[3] >= 60 and sum >= 180:
        f.write('%s\t%s\n' % (x[0], '及格'))
    else:
        f.write('%s\t%s\n' % (x[0], '不及格'))
s.close()
f.close()

# 例5-8
'''
"car_data.txt"文件是以英文逗号分隔的数据文本文件(文件局部如图所示),
记录了某出租汽车公司部分车辆某日0:00~23:00的车辆位置,无标题行。对应列分别是时间、车牌号、北纬、东经。
因协助查找该日发生在北纬31.2222-31.2333,东经121.45-121.55区域内的案件,
编写程序,找到并打印位于该区域内该出租车公司的车辆信息
'''
min_n, min_e =31.2222, 121.45 # 设置所要查找的区域经纬度
max_n, max_e =31.2333, 121.55 # 设置所要查找的区域经纬度
LS = list(open('car_data.txt')) # 使用快速列表方式读取car_data.txt文件,并赋值为LS
#print(LS)
car = [] # 设置一个空列表用于存储处理后的数据
for s in LS:
    carone = s[:-1].split(',') # 切片取值索引为0到-1(不含)是为了去掉换行符\n
    # split()通过指定分隔符,对字符串进行切片
    #print(carone)
    car.append(carone) # car列表变成了二维列表
#print(car)
#print(len(car))
print('在该区间出现的车辆有:')
for t in range(len(car)):
    if (min_n < float(car[t][2]) < max_n) and (min_e < float(car[t][3]) < max_e):
        # 二维列表索引,第t个列表中的第2个元素和第三个元素分别为维度和经度
        print('时间:%s\t车牌:%s\t北纬:%s,东经:%s' % (car[t][0], car[t][1], car[t][2], car[t][3]))
        # 二维列表索引,第t个列表中的第0、1、2、3个元素分别为时间、车牌、纬度、经度


# 5.3.2词频分析
# 例5-9 统计著名黑人领袖马丁·路德金演讲“I Have a Dream”的词汇出现频次。
'''
编程思想:读取文本文件,用lower()方法将所有字符转为小写并用split()方法按空格分隔单词,将所有单词放在列表speech中。
定义一个空字典dic,用循环结构遍历列表speech,将单词作为字典的键,统计每个单词出现的次数,作为字典的值。
'''
f = open('i_have_a_dream.txt') # 使用open()打开i_have_a_dream.txt文本文件,创建一个文件对象并赋值为f
speech_text = f.read() # 对文件对象f进行读取,并赋值为speech_text
#print(speech_text)
#print(type(speech_text))
f.close() # 关闭文件对象f,虽然文件已关闭,但文件里的数据已经赋值为speech_text存放在内存中以便调用
speech = speech_text.lower().split()
# 使用lower()方法将字符串speech_text里的字符转为小写,并使用split()方法按空格分隔单词,将所有单词放到列表speech中
#print(speech)
dic = {} # 创建空列表dic
for word in speech: # 对speech列表中的元素进行遍历
    if word not in dic: # 如果遍历到的词语不在字典dic中
        dic[word]=1 # 将遍历到的词语设置为键,值(该词语出现的次数)设置为1,将此键值对添加到字典dic中
    else: # 如果遍历到的词语在字典dic中
        dic[word]+=1 # 更改键(遍历到的词语)对应的值(该词语出现的次数),其值在原基础上加1
#print(dic)
swd = sorted(list(dic.items()), key=lambda tup: tup[1], reverse=True)
# items()方法返回字典的项(键值对)。list()方法以列表形式返回可遍历的(键, 值)元组数组
# lambda构造匿名函数,以元组中索引为1是的元素作为排序依据,即tup[1]
# reverse = True 表示降序排列,最后得到按照词语出现次数降序排列的(键, 值)元组的列表,赋值为swd
#print(swd)
for kword, times in swd: # 对列表swd中元组的元素依次遍历,并输出
    print(kword, times)

'''
sorted()函数用法
sorted() 函数对所有可迭代的对象(字符串、列表、元组、字典、集合)进行排序操作,返回重新排序的列表
语法
sorted(iterable, key=None, reverse=False)
iterable – 可迭代对象。
key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse – 排序规则:reverse = True 降序,reverse = False 升序(默认)。

sort与sorted的区别:
sort是应用在list上的方法,sorted可以对所有可迭代的对象进行排序操作。
list的sort方法返回的是对已存在的列表操作后的结果,而内建函数sorted方法返回的是一个新的list,而不是在原来的基础上进行的操作。
语法
sorted语法:sorted(iterable,key=None,reverse=False)
sort语法:sort(key=None,reverse=False)
参数说明:
iterable--可迭代的对象
key--用列表元素的某个属性或函数作为关键字
reverse--排序规则,reverse=True降序,reverse=False升序(默认)
区别:
对于一个无序列表a,调用a.sort(),对a排序后返回a,sort()函数修改待排序的列表内容
而对于一个无序列表a,调用sorted(a),对a排序后返回一个新的列表,对a无影响
'''

# 去除停用词
'''
在例5-9中,the等虚词出现的频率很高,但在实际运用中,统计这种词的出现频率意义不大,所以我们可以讲这些
不参加统计的词(停用词,stop_words)以列表结构形成文本文件,在编写代码输出结果时添加条件,
将不含停用词的词频结果输出出来。
'''
f = open('i_have_a_dream.txt')
speech_text = f.read()
f.close()
speech = speech_text.lower().split()
dic = {}
for word in speech:
    if word not in dic:
        dic[word] = 1
    else:
        dic[word] += 1
swd = sorted(list(dic.items()), key=lambda tup: tup[1], reverse=True)
f1 = open('stop_word_list.txt') # 打开停用词文本文件
stop_wds = f1.read() # 对文件对象f进行读取,并赋值为stop_wds
f1.close()
for kword, times in swd:
    if kword not in stop_wds: # 判断统计词频的词是否在停用词文件中,如果不在,输出结果
        print(kword, times)


# 5.3.3第三方库jieba和中文词频分析
'''
英文词汇之间有天然的空格分隔,而中文之间没有,而且中文随着字词长短的变化,不同组合语义差别很大,要对中文进行词频分析,
首先要解决词汇的分割问题,而Python的第三方库jieba(“结巴”)是一个用于中文词汇分割的函数库,
运用jieba.lcut()方法(0.39版本以上),可高效准确地实现将字符串中的中文词汇分割,精确返回词汇列表。
'''
# 例5-10 统计朱自清散文《荷塘月色》的词汇出现频次
import jieba  # 导入jieba第三方库
f = open('荷塘月色.txt')
article_text = f.read()
f.close()
article = jieba.lcut(article_text) # 运用jieba.lcut()方法将字符串中的中文词汇分割,返回词汇列表
#print(article)
dic = {}
for word in article:
    if word not in dic:
        dic[word] = 1
    else:
        dic[word] += 1
swd = sorted(list(dic.items()), key=lambda tup: tup[1], reverse=True)
f1 = open('中文虚词列表.txt') # 打开中文虚词列表
stop_wds = f1.read()
f1.close()
for kword, times in swd:
    if kword not in stop_wds:
        print(kword, times)


# 5.3.4 词语可视化和第三方库wordcloud
'''
Python的第三方库wordcloud是一种能将词语渲染成大小、颜色不一的可视化呈现形式“词云”的函数库。其效果能将枯燥呆板的文字
以直观的艺术效果展示出来。创建词云时,先引用第三方库wordcloud,将其核心类WordCloud实例化为词云对象,

实例化对象的常用参数有:
background_color		词云背景色,默认为黑
width,height			宽和高(像素)
font_path				字体文件的路径
max_font_size			最大字号
max_words			    最多容纳词汇数,默认200

词云对象有两个方法:genaerate()和to_file(),功能分别是将文本生成词云和将词云保存为图片
'''
import wordcloud
txt = '什么 是 快乐星球, 什么 是 快乐星球,如果 你 想 知道 什么 是 快乐星球 的 话,我 现在 就 带 你 研究!'
w = wordcloud.WordCloud(background_color='white',
                      width=150,
                      height=120,
                      max_font_size=48,
                      font_path='C:/Windows/Fonts/simhei.ttf') # 实例化词云对象

w.generate(txt) # 将文本生成词云
w.to_file('D:\\Pythonlesson\\Chapter5\\快乐星球云词图.png')  # 保存词云

# 例5-11 将朱自清散文《荷塘月色》的词汇出现频次结果生成词云图
import wordcloud
import jieba  # 导入jieba第三方库
f = open('荷塘月色.txt')
article_text = f.read()
f.close()
article = jieba.lcut(article_text) # 运用jieba.lcut()方法将字符串中的中文词汇分割,返回词汇列表
text = ''
for i in article:
    text = text+str(i)+' ' # 将列表中的词汇遍历并以空格分隔保存到text字符串中
w = wordcloud.WordCloud(background_color='white',
                      width=400,
                      height=300,
                      max_font_size=48,
                      font_path='C:/Windows/Fonts/simhei.ttf') # 实例化词云对象
w.generate(text) # 将文本生成词云
w.to_file('D:\\Pythonlesson\\Chapter5\\荷塘月色云词图.png')  # 保存词云