python数据分析与可视化_葡萄酒评论分析报告_pandas库
任务要求
问题重述
文件“winemag-data.csv” 包含
编号、国家、描述、评分、价格、省份
等6列和12974行葡萄酒评论的数据。数据格式如下所示:
number,country,description,points,price,province
30,France,“Red cherry fruit comes laced with…”,86,15,Beaujolais
50,Italy,“This blend of Nero Avola and Syrah…”,86,15,Sicily
100,US,“Fresh apple, lemon and pear flavors…”,88,18,New York
通过分析这些数据,用户可以根据产地、评份、价格等挑选适合自己的葡萄酒,商家可以分析消费者的购买行为习惯,可以更加准确地提供适合市场的产品,精准定位客户。
要求
- 输入
'国家名列表'
,统计文件中出现的葡萄酒生产国家,输出不重复的国家名列表,按字母表升序排序, 若国家名数据缺失,略过该条数据,返回值中不包含空字符串元素 - 输入
'平均分'
,计算每个国家的葡萄酒的平均得分( 保留最多2位小数),返回值为国家名和得分的列表 - 输入
'平均分排序'
,计算每个国家的葡萄酒的平均得分,返回值为国家名和得分的列表, 按评分由高到低降序排列 - 输入
'评分最高'
,输出评分最高的十款葡萄酒的编号、出产国、评分和价格,按评分降序输出 - 输入
'价格最高'
,输出价格最高的二十款葡萄酒的编号、出产国、评分和价格,按价格降序输出 - 输入
'葡萄酒评分'
,统计各个评分的葡萄酒数量是多少?
输出各个评分的葡萄酒数量的列表,按评分升序排序;
输出拥有葡萄酒数量最多的评分和数量;
输出拥有葡萄酒数量最多的评分的葡萄酒的平均价格 - 输入其他时,输出“输入错误”
读取文件示例:
def csv_to_ls(file):
"""接收文件名为参数,用pandas读取数据为dataframe格式,
再将其数据部分(values)用tolist()方法转为二维列表,
返回这个二维列表。
@参数 file:文件名,字符串类型
"""
wine_list = pd.read_csv(file).values.tolist()
# print(wine_list)
return wine_list
输入输出示例,示例仅为格式展示,与测试用例无关
示例 1
输入:
国家名列表
输出:
[‘Argentina’, ‘Armenia’, … ‘US’, ‘Ukraine’, ‘Uruguay’]
示例 2
输入:
平均分
输出:
[[‘Argentina’, 86.72], [‘Armenia’, 87.0],… [‘Ukraine’, 83.0], [‘Uruguay’, 88.0]]
示例 3
输入:
葡萄酒评分
输出:
[[80, 38], [81, 71], … [95, 140], [96, 50], [97, 26], [98, 8], [99, 3]] [86, 1743]
31.02
编程思路
- 统计文件中出现的葡萄酒生产国家,输出不重复的国家名列表,按字母表升序排序, 若国家名数据缺失,略过该条数据,返回值中不包含空字符串元素。
- 计算每个国家的葡萄酒的平均得分,返回值为国家名和得分的列表
- 计算每个国家的葡萄酒的平均得分,返回值为国家名和得分的列表,按评分由高到低降序排列
- 评分最高的十款葡萄酒的编号、出产国、评分和价格,按评分降序输出
- 价格最高的二十款葡萄酒的编号、出产国、评分和价格,按价格降序输出
- 统计各个评分的葡萄酒数量是多少?输出包含评分和数量的列表
- 输出拥有葡萄酒数量最多的评分和数量
- 输出拥有葡萄酒数量最多的评分的葡萄酒的平均价格
相关函数及实现方法说明
函数部分
在列表中添加元素,
append()
函数
list.append()
方法向list列表末尾追加元素
对数据进行排序,
sort()
函数
list.sort(cmp=None, key=None, reverse=False)
参数说明:
(1)cmp,可选参数, 如果指定了该参数会使用该参数的方法进行排序(可自定义函数)
(2)key,可迭代对象中的某一个元素来进行排序,例如有这样一个列表:
students = [('john','A',15), ('jane','B',12), ('dave','B',10)]
现在想指定每个元组中的第三个元素作为标准进行排序
sorted (students, key = lambda student : student[2])
注意上面使用了lambda函数,使用方法与matlab中的匿名函数相似
(3)reverse,排序规则,reverse = True
降序,reverse = False
升序(默认)
返回浮点数x的四舍五入值,
round()
函数
参数说明:round(number,ndigits)
ndigits:指定要保留的小数位数,可以是正整数或负整数。
当ndigits为正数时好理解,值得注意的是,当ndigits为负数时,例如当ndigits为-2时,表示保留到百位(即小数点左边2位的位置)
返回对象的长度。例如返回列表中的对象的个数,
len()
函数
方法部分
接收csv数据并返回列表,转化成np或pd容易处理的格式
wine_list = pd.read_csv(file).values.tolist()
注意返回的wine_list是一个二维列表
返回不重复的国家名列表方法
使用循环取出wine_list中的每个元素for x in wine_list:
,此时x是原始csv数据集中的每一行
判断该元素是否在构建的country_list列表中,由于此时x包含的是数据中一行的信息,使用x[COUNTRY]
可以去除该行数据的国家名称
使用if x[COUNTRY] not in country_list:
判断是否重复,若不重复则使用append()
函数添加进去
列表推导式的使用
列表推导式是一种创建列表的简洁语法
列表推导式格式为:[表达式 for 变量 in 列表]
或者[表达式 for 变量 in 列表 if 条件]
对于后一种格式,列表推导式的执行步骤为:
(1)执行for循环
(2)执行if判断条件
(3)执行表达式中的内容
下面是一个实现平方数的例子
squares = [i**2 for i in range(10) if i>=2]
与以下语句等价:
squares = []
for i in range(10):
if i >= 2:
squares.append(i**2)
列表切片
切片是为了获得序列某个区间的元素序列,用切片截取列表中任何部分来获得一个新的列表,也可以进行元素的增、删、改(替换)
通过连续切片赋值方法更新列表中的数据,将原列表中切片中元素新的列表中的元素替换。值可以与原有元素的数据类型不同。
参数说明:切片操作通过使用两个冒号分隔3个数字来实现
第一个数字表示切片的开始位置,默认为0
第二个数字表示切片的终止位置(但不包含该位置的元素),默认取到列表的长度
第三个数字为切片的步长,默认为1,当省略步长时,可以同时省略后一个冒号
相关技巧:
list[:-1] # 取出除最后一个元素外的所有元素
list[::-1]) # 从右向左取全部成员
代码实现
子函数部分
- 输入
'国家名列表'
,统计文件中出现的葡萄酒生产国家,输出不重复的国家名列表,按字母表升序排序, 若国家名数据缺失,略过该条数据,返回值中不包含空字符串元素
def country_ls(wine_list):
"""接收列表格式的葡萄酒数据为参数,略过标题行,返回不重复的国家名列表,按字母表升序排序,
若国家名数据缺失,略过该条数据,返回值中不包含空字符串元素。
@参数 wine_list:葡萄酒数据,列表类型
"""
country_list = []
for x in wine_list:
if x[COUNTRY] not in country_list:
country_list.append(x[COUNTRY])
country_list.sort()
# print(country_list)
return country_list
- 输入
'平均分'
,计算每个国家的葡萄酒的平均得分( 保留最多2位小数),返回值为国家名和得分的列表
def avg_point(wine_list, country):
"""接收列表格式的葡萄酒数据和国家名列表为参数,计算每个国家的葡萄酒的平均得分,
返回值为国家名和得分的列表。
@参数 wine_list:葡萄酒数据,列表类型
@参数 country:国家名,列表类型
"""
avg_point_per_country = []
for country_name in country:
point_of_country = [x[POINTS] for x in wine_list[1:] if x[COUNTRY] == country_name] # 每个国家的葡萄酒评分列表
avg_point_per_country.append([country_name, round(sum(point_of_country) / len(point_of_country), 2)])
return avg_point_per_country # 返回每个国家的葡萄酒的平均评分
- 输入
'平均分排序'
,计算每个国家的葡萄酒的平均得分,返回值为国家名和得分的列表, 按评分由高到低降序排列
def avg_point_sort(wine_list, country):
"""接收列表格式的葡萄酒数据和国家名列表为参数,计算每个国家的葡萄酒的平均得分,
返回值为国家名和得分的列表,按评分由高到低降序排列。
@参数 wine_list:葡萄酒数据,列表类型
@参数 country:国家名,列表类型
"""
avg_point_per_country = []
for country_name in country:
point_of_country = [float(x[POINTS]) for x in wine_list[1:] if x[COUNTRY] == country_name] # 每个国家的葡萄酒评分列表
avg_point_per_country.append([country_name, round(sum(point_of_country) / len(point_of_country), 2)])
return sorted(avg_point_per_country, key=lambda x: x[1], reverse=True) # 返回每个国家的葡萄酒的平均评分
- 输入
'评分最高'
,输出评分最高的十款葡萄酒的编号、出产国、评分和价格,按评分降序输出
def top_10_point(wine_list):
"""接收列表格式的葡萄酒数据参数,返回评分最高的十款葡萄酒的编号、出产国、评分和价格,按评
分降序输出。
需要注意的是评分可能有缺失值,此时该数据为nan
if math.isnan(x) == False可用于判定x的值是不是nan
nan的数据类型是float,不可以直接用字符串判定方法。
@参数 wine_list:葡萄酒数据,列表类型
"""
wine_top_point = [[x[NUMBER], x[COUNTRY], x[POINTS], x[PRICE]] for x in wine_list if math.isnan(x[POINTS]) is False]
return sorted(wine_top_point, key=lambda x: x[2], reverse=True)[:10]
#注意这里切片的使用
- 输入
'价格最高'
,输出价格最高的二十款葡萄酒的编号、出产国、评分和价格,按价格降序输出
def top_20_price(wine_list):
"""接收列表格式的葡萄酒数据参数,返回价格最高的二十款葡萄酒的编号、出产国、评分和价格,按价
格降序输出。
@参数 wine_list:葡萄酒数据,列表类型
需要注意的是价格可能有缺失值,此时该数据为nan
if math.isnan(x) == False可用于判定x的值是不是nan
nan的数据类型是float,不可以直接用字符串判定方法。
"""
wine_top_price = [[x[NUMBER], x[COUNTRY], x[POINTS], x[PRICE]]for x in wine_list if math.isnan(x[PRICE]) is False]
return sorted(wine_top_price, key=lambda x: x[3], reverse=True)[:20]
- 输入
'葡萄酒评分'
,统计各个评分的葡萄酒数量是多少?
输出各个评分的葡萄酒数量的列表,按评分升序排序;
输出拥有葡萄酒数量最多的评分和数量;
输出拥有葡萄酒数量最多的评分的葡萄酒的平均价格
统计各个评分的葡萄酒数量是多少
def amount_of_point(wine_list):
"""接收列表格式的葡萄酒数据参数,返回每个评分的葡萄酒数量,忽略没有评分的数据
例如[...[84, 645], [85, 959],...]表示得分为84的葡萄酒645种,得分85的葡萄酒有959种。
@参数 wine_list:葡萄酒数据,列表类型
"""
point_list = []
for x in wine_list:
if x[POINTS] not in point_list:
point_list.append(x[POINTS])
point_list.sort()
amount = [x[POINTS] for x in wine_list]
amount_of_points = [[point, amount.count(point)] for point in point_list]
# print(amount_of_points)
return amount_of_points
输出各个评分的葡萄酒数量的列表,按评分升序排序;
def most_of_point(amount_of_points):
"""接收每个评分的葡萄酒数量的列表为参数,返回获得该分数数量最多的评分和数量的列表。
@参数 amount_of_points:每个评分的葡萄酒数量,列表类型
"""
return sorted(amount_of_points, key=lambda x: x[1], reverse=True)[0]
输出拥有葡萄酒数量最多的评分和数量
def avg_price_of_most_point(wine_list, most_of_points):
"""接收列表格式的葡萄酒数据和获得最多的评分及数量的列表为参数
忽略缺失价格的数据,返回这个分数的葡萄酒的平均价格,保留2位小数。
@参数 wine_list:葡萄酒数据,列表类型
@参数 most_of_points:获得最多的评分及数量,列表类型
"""
price_of_point = [x[PRICE] for x in wine_list if x[POINTS] == most_of_points[0] and math.isnan(x[PRICE]) is False]
avg_price_of_point = sum(price_of_point) / len(price_of_point)
# print(price_of_point)
return round(avg_price_of_point, 2)
输出拥有葡萄酒数量最多的评分的葡萄酒的平均价格
使用之前写好的avg_price_of_most_point()
函数即可
avg_price_of_most_point(wine, most_point)
完成以上子函数编写后,接收一个字符串为参数,根据参数值调用不同函数
judge()
函数完成任务
def judge(txt):
filename = './data/winemag-data.csv'
wine = csv_to_ls(filename)
country = country_ls(wine)
if txt == '国家名列表':
print(country)
elif txt == '平均分':
print(avg_point(wine, country)) # 每个国家的葡萄酒的平均得分
elif txt == '平均分排序':
print(avg_point_sort(wine, country)) # 每个国家的葡萄酒的平均得分降序输出
elif txt == '评分最高':
print(top_10_point(wine)) # 评分最高的十款葡萄酒的编号、出产国、评分和价格,按评分降序输出
elif txt == '价格最高':
print(top_20_price(wine)) # 价格最高的二十款葡萄酒的编号、出产国、评分和价格,按价格降序输出
elif txt == '葡萄酒评分':
amount_point = amount_of_point(wine)
most_point = most_of_point(amount_point)
print(amount_point) # 各个评分的葡萄酒数量
print(most_point) # 拥有葡萄酒数量最多的评分和数量
print(avg_price_of_most_point(wine, most_point)) # 拥有葡萄酒数量最多的评分的葡萄酒的平均价格
else:
print('输入错误')
最终实现代码
import pandas as pd
import math
# 定义符号常量,用于索引,使之具有清晰的语义
NUMBER = 0
COUNTRY = 1
DESCRIPTION = 2
POINTS = 3
PRICE = 4
PROVINCE = 5
def csv_to_ls(file):
"""接收文件名为参数,逐行读取文件中的数据,根据逗号切分每行数据为列表类型,
作为二维列表的一个元素,返回二维列表。
@参数 file:文件名,字符串类型
"""
wine_list = pd.read_csv(file).values.tolist()
# print(wine_list)
return wine_list
def country_ls(wine_list):
country_list = []
for x in wine_list:
if x[COUNTRY] not in country_list:
country_list.append(x[COUNTRY])
country_list.sort()
# print(country_list)
return country_list
def avg_point(wine_list, country):
avg_point_per_country = []
for country_name in country:
point_of_country = [x[POINTS] for x in wine_list[1:] if x[COUNTRY] == country_name] # 每个国家的葡萄酒评分列表
avg_point_per_country.append([country_name, round(sum(point_of_country) / len(point_of_country), 2)])
return avg_point_per_country # 返回每个国家的葡萄酒的平均评分
def avg_point_sort(wine_list, country):
avg_point_per_country = []
for country_name in country:
point_of_country = [float(x[POINTS]) for x in wine_list[1:] if x[COUNTRY] == country_name] # 每个国家的葡萄酒评分列表
avg_point_per_country.append([country_name, round(sum(point_of_country) / len(point_of_country), 2)])
return sorted(avg_point_per_country, key=lambda x: x[1], reverse=True) # 返回每个国家的葡萄酒的平均评分
def top_10_point(wine_list):
wine_top_point = [[x[NUMBER], x[COUNTRY], x[POINTS], x[PRICE]] for x in wine_list if math.isnan(x[POINTS]) is False]
return sorted(wine_top_point, key=lambda x: x[2], reverse=True)[:10]
def top_20_price(wine_list):
wine_top_price = [[x[NUMBER], x[COUNTRY], x[POINTS], x[PRICE]]for x in wine_list if math.isnan(x[PRICE]) is False]
return sorted(wine_top_price, key=lambda x: x[3], reverse=True)[:20]
def amount_of_point(wine_list):
point_list = []
for x in wine_list:
if x[POINTS] not in point_list:
point_list.append(x[POINTS])
point_list.sort()
amount = [x[POINTS] for x in wine_list]
amount_of_points = [[point, amount.count(point)] for point in point_list]
# print(amount_of_points)
return amount_of_points
def most_of_point(amount_of_points):
return sorted(amount_of_points, key=lambda x: x[1], reverse=True)[0]
def avg_price_of_most_point(wine_list, most_of_points):
price_of_point = [x[PRICE] for x in wine_list if x[POINTS] == most_of_points[0] and math.isnan(x[PRICE]) is False]
avg_price_of_point = sum(price_of_point) / len(price_of_point)
# print(price_of_point)
return round(avg_price_of_point, 2)
def judge(txt):
filename = './data/winemag-data.csv'
wine = csv_to_ls(filename)
country = country_ls(wine)
if txt == '国家名列表':
print(country)
elif txt == '平均分':
print(avg_point(wine, country)) # 每个国家的葡萄酒的平均得分
elif txt == '平均分排序':
print(avg_point_sort(wine, country)) # 每个国家的葡萄酒的平均得分降序输出
elif txt == '评分最高':
print(top_10_point(wine)) # 评分最高的十款葡萄酒的编号、出产国、评分和价格,按评分降序输出
elif txt == '价格最高':
print(top_20_price(wine)) # 价格最高的二十款葡萄酒的编号、出产国、评分和价格,按价格降序输出
elif txt == '葡萄酒评分':
amount_point = amount_of_point(wine)
most_point = most_of_point(amount_point)
print(amount_point) # 各个评分的葡萄酒数量
print(most_point) # 拥有葡萄酒数量最多的评分和数量
print(avg_price_of_most_point(wine, most_point)) # 拥有葡萄酒数量最多的评分的葡萄酒的平均价格
else:
print('输入错误')
if __name__ == '__main__':
text = input()
judge(text)