目录
原题背景
最近,“city 不 city”这一网络流行语在外国网红的推动下备受关注。随着我国过境免签政策的落实,越来越多外国游客来到中国,通过网络平台展示他们在华旅行的见闻,这不仅推动了中国旅游业的发展,更是在国际舞台上展现了一个 真实而生动的中国,一举多得。
假设外国游客入境后能在中国境内逗留 144 小时,且能从任一城市附近的机场出境。由于每个城市景点较多,为了便于外国游客能够游览到更多的城市,现假定“每个城市只选择一个评分最高的景点游玩”,称之为“城市最佳景点游览原 则”。
现有一个包含中国(不含港澳台)352 个城市的旅游景点的数据集,每个城 市的 csv 文件中有 100个景点,每个景点的信息包含有景点名称、网址、地址、 景点介绍、开放时间、图片网址、景点评分、建议游玩时长、建议游玩季节、门票信息、小贴士等。
背景分析
提取关键信息:
(1)“城市最佳景点游览原则”:假设外国游客入境后能在中国境内逗留 144 小时,且能从任一城市附近的机场出境。由于每个城市景点较多,为了便于外国游客能够游览到更多的城市,现假定“每个城市只选择一个评分最高的景点游玩”,称之为“城市最佳景点游览原则”。
(2)数据说明:现有一个包含中国(不含港澳台)352 个城市的旅游景点的数据集,每个城 市的 csv 文件中有 100个景点,每个景点的信息包含有景点名称、网址、地址、 景点介绍、开放时间、图片网址、景点评分、建议游玩时长、建议游玩季节、门票信息、小贴士等。
分析题目背景:
本题为了帮助外国游客在有限的时间内游览中国的最佳景点,我们需要利用数据集中的信息进行一些分析和建模。首先根据关键信息(1),我们需要从每个城市的数据集中提取评分最高的景点信息。假设我们已经有了包含352个城市旅游景点的CSV文件。对每个城市,找到评分最高的景点,并记录其信息。我们可以编写一个脚本来处理这些CSV文件,并提取所需的数据。
其次,考虑到游客在144小时内需要游览多个城市,并且可能需要在不同城市之间进行交通转换,我们可以使用以下几种数学模型进行优化:
旅行商问题 (TSP):
这个问题可以被看作是一个典型的旅行商问题,其中每个城市是一个节点,景点是游客需要访问的地方。目标是找到一个路径,使得总的旅行时间或距离最小,同时确保游客在每个城市的停留时间在合理范围内。
时变网络模型:
考虑到不同交通方式(如高铁、飞机)的时间和费用,我们可以构建一个时变网络模型来优化旅行路径和时间。
下面,我们将根据具体的问题进行分析和解答。
问题一
原题
请问 352 个城市中所有 35200 个景点评分的最高分(Best Score,简称 BS)是多少?全国有多少个景点获评了这个最高评分(BS)?获评了这个最高评分(BS)景点最多的城市有哪些?依据拥有最高评分(BS)景点数量的多少排序,列出前 10 个城市。
思路
Step1:数据读取与处理
首先,我们需要读取所有352个城市的CSV文件,并提取每个景点的评分数据。我们可以使用Python中的Pandas库来处理这些数据。
其次,因为数据中存在数据缺失和类型不匹配问题,我们需要将空值剔除或者用0来填补,并将str型数据转换成float型,进行数据去除Step2:计算最高评分(Best Score, BS)
我们需要遍历所有景点的评分数据,找到最高评分(BS)。然后统计获得最高评分(BS)的景点数量以及这些景点所在的城市。Step3:统计各城市的最高评分(BS)景点数量
我们需要统计每个城市中获得最高评分(BS)的景点数量,并按数量排序,列出前10个城市。
代码
import os
import pandas as pd
import numpy as np
import pandas as pd
import os
data = os.walk("E:\桌面\数学建模\\2024年第五届“华数杯”全国大学生数学建模竞赛赛题\\2024年第五届“华数杯”全国大学生数学建模竞赛赛题\C题\附件")
result=[]
all=0
max=0
for path, folder_list, file_list in data:
for file_name in file_list:
# print(file_name)
if file_name.endswith('.csv'):
city=file_name.split('.')[0]
file_abs_path = os.path.join(path, file_name)
ext = file_abs_path.rsplit(".",1)[-1]
if ext == "csv":
te ={}
# print(file_abs_path)
df = pd.read_csv(file_abs_path)
# df['名字'].unique().sum()
df.drop_duplicates(subset='名字', inplace=True)
df=df.fillna(value=0.0)
df['评分'].replace('--',0.0,inplace=True)
df['评分']=df['评分'].astype('float')
# 假设 df 是你的 DataFrame,并且 '评分' 是列名
# 选择评分为 5.0 的所有行
top_scored_rows = df.loc[df['评分'] == 5.0]
# 使用 shape 属性来获取这些行的数量,[0] 表示获取行数
count_top_scored = top_scored_rows.shape[0]
# print(f"评分为 5.0 的景点数量是:{count_top_scored}")
te[city] = count_top_scored
result.append(te)
all+=count_top_scored
if count_top_scored > max:
max=count_top_scored
print(result)
print(all)
with open('./t1-2.csv','w',encoding='utf-8') as f:
f.write(str(result))
# 将列表转换为一个字典
city_scores = {city: score for item in result for city, score in item.items()}
# 使用 sorted 函数和一个 lambda 函数按值对字典进行排序
# reverse=True 表示降序排序
sorted_city_scores = sorted(city_scores.items(), key=lambda x: x[1], reverse=True)
result_sort = []
# 打印排序后的结果
for city, score in sorted_city_scores:
temp={}
# print(f"{city}: {score}")
temp[city]=score
result_sort.append(temp)
print(result_sort)
with open('./t1-3.csv','w',encoding='utf-8') as f:
f.write(str(result_sort))
问题二
原题
假如外国游客遵循“城市最佳景点游览原则”,结合城市规模、环境环保、人文底蕴、交通便利,以及气候、美食等因素,请你对 352 个城市进行综合评价,选出“最令外国游客向往的 50 个城市”。
思路
要对352个城市进行综合评价,选出“最令外国游客向往的50个城市”,我们需要建立一个多因素评价模型。这些因素包括城市规模、环境环保、人文底蕴、交通便利、气候、美食等。我们可以通过加权评分的方法来综合评估这些城市。Step1: 定义评价指标
城市规模:可以用城市人口或GDP来衡量。
环境环保:可以用PM2.5平均浓度或城市绿化率来衡量。
人文底蕴:可以用历史遗迹数量、博物馆数量等来衡量。
交通便利:可以用公共交通覆盖率、交通便捷性等来衡量。
气候:可以用气候舒适度指数来衡量。
美食:可以用美食评价、餐厅数量等来衡量。
Step2: 收集数据
假设我们已经收集了上述指标的数据,可以用一个CSV文件来表示,其中每一列代表一个城市,每一列代表一个评价指标。
因为在原始的数据文件中指包含地点名称、网址、地址、景点介绍、开放时间、图片网址、评分、建议游玩时长、建议游玩季节、门票信息、小贴士等。并没有题目中的城市规模、环境保护、人文底蕴等信息,所以这部分数据需要我们自己补充。Step3: 标准化数据
由于各个指标的量纲不同,需要对数据进行标准化处理。Step4: 加权评分
给每个指标分配权重,根据加权评分计算每个城市的综合评分。Step5: 选出前50个城市
根据综合评分进行排序,选出前50个城市。
代码
1.模拟数据
import os
import numpy as np
import pandas as pd
# 设定随机种子以确保结果具有可重复性
np.random.seed(666)
# 定义评价指标
eval_criteria = ['城市规模', '环境环保', '人文底蕴', '交通便利', '气候', '美食']
# 指定文件夹路径
folder = 'E:\桌面\数学建模\\2024年第五届“华数杯”全国大学生数学建模竞赛赛题\\2024年第五届“华数杯”全国大学生数学建模竞赛赛题\C题\附件'
output_folder = 'E:\桌面\数学建模\\2024年第五届“华数杯”全国大学生数学建模竞赛赛题\\2024年第五届“华数杯”全国大学生数学建模竞赛赛题\C题\附件1'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for path, folder_list, file_list in os.walk("E:\桌面\数学建模\\2024年第五届“华数杯”全国大学生数学建模竞赛赛题\\2024年第五届“华数杯”全国大学生数学建模竞赛赛题\C题\附件"):
for file_name in file_list:
# print(file_name)
if file_name.endswith('.csv'):
city=file_name.split('.')[0]
file_abs_path = os.path.join(path, file_name)
ext = file_abs_path.rsplit(".",1)[-1]
if ext == "csv":
te ={}
# print(file_abs_path)
df = pd.read_csv(file_abs_path)
# 假设CSV文件的第一列是景点名称
attraction_names = df.iloc[:, 0]
# 为每个景点生成评价指标数据
data = {criterion: np.random.rand(len(attraction_names)) for criterion in eval_criteria}
# 创建DataFrame,其中每行代表一个景点,每列代表对应的评价指标
df_attractions = pd.DataFrame(data, index=attraction_names)
# 保存为新的CSV文件
output_file_path = os.path.join(output_folder, f'{city}_random.csv')
df_attractions.to_csv(output_file_path)
2.计算总分--熵权法
entropy_weight
函数是用来实现熵权法(Entropy Weight Method)的,这是一种多准则决策分析中用于确定指标权重的方法。熵权法是一种客观赋权方法,它基于各指标的信息熵来计算权重,反映指标的离散程度或变异性。具有较高离散度的指标将获得较高的权重,因为它们在决策中提供更多信息。
TOPSIS(Technique for Order Preference by Similarity to Ideal Solution)方法,它是一种基于理想点和负理想点的多准则决策分析技术。TOPSIS 方法通过比较各个备选方案与理想解和负理想解的距离来评估它们的相对优劣。
representative_attractions = []
city_files = [f for f in os.listdir(folder) if f.endswith('.csv')]
# 存储每个城市和代表景点的信息
representative_attractions = []
for city_file in city_files:
city_data = pd.read_csv(os.path.join(folder, city_file))
# 获取城市名称(去掉扩展名)
city_name = os.path.splitext(city_file)[0]
# 检查数据是否为空
if city_data.empty:
print(f"{city_file} 数据为空,跳过.")
continue
try:
# 计算每个景点的总评分
city_data['总评分'] = city_data[['城市规模', '环境环保', '人文底蕴', '交通便利', '气候', '美食']].sum(axis=1)
# 找到评分最高的景点
# representative={}
representative = city_data.loc[city_data['总评分'].idxmax()]
representative['城市'] = city_name.replace('_random','') # 将城市名称添加到代表景点的信息中
representative_attractions.append(representative)
except ValueError as e:
print(f"处理 {city_file} 时发生错误: {e}")
# 转换为DataFrame
if representative_attractions:
rep_df = pd.DataFrame(representative_attractions)
else:
print("没有找到任何代表景点。")
def entropy_weight(data):
# 标准化数据
norm_data = data / data.sum()
# 计算熵
k = 1.0 / np.log(len(data))
entropy = -k * (norm_data * np.log(norm_data + 1e-10)).sum(axis=0)
# 计算权重
d = 1 - entropy
weights = d / d.sum()
return weights
# 选择指标列
indicator_columns = ['城市规模', '环境环保', '人文底蕴', '交通便利', '气候', '美食']
weights = entropy_weight(rep_df[indicator_columns])
# TOPSIS计算函数
def topsis(data, weights):
# 指标值的正负属性
benefit_index = [True] * len(weights) # 所有指标都是优越指标
# 正理想解和负理想解
ideal_best = data.max()
ideal_worst = data.min()
# 计算距离
distance_to_best = np.sqrt(((data - ideal_best) ** 2).sum(axis=1))
distance_to_worst = np.sqrt(((data - ideal_worst) ** 2).sum(axis=1))
# 计算相似度
scores = distance_to_worst / (distance_to_best + distance_to_worst)
return scores
# 计算代表景点的TOPSIS得分
topsis_scores = topsis(rep_df[indicator_columns], weights)
# 将得分添加到DataFrame
rep_df['得分'] = topsis_scores
# 输出前50名城市
top_cities = rep_df.sort_values(by='得分', ascending=False).head(50)
import pandas as pd
import numpy as np
import os
# 假设 top_cities 是已经存在的 DataFrame
# 保留“名字”和“城市”列(请根据实际情况替换列名,如“名字”可能实际为“景点名称”等)
top_cities_reduced = top_cities[['名字', '城市','得分']]
# 随机生成“门票”和“游玩时长”两列
np.random.seed(0) # 设定随机种子以保证结果可复现
top_cities_reduced['门票'] = np.random.randint(50, 200, size=top_cities_reduced.shape[0]) # 门票价格在50到200之间
top_cities_reduced['游玩时长'] = np.random.randint(1, 10, size=top_cities_reduced.shape[0]) # 游玩时长在1到10小时之间
# 指定保存路径
folder = '..\\C题'
# 构造新表的文件名
filename = 'top_cities.csv'
filepath = os.path.join(folder, filename)
# 将新表保存到指定路径
top_cities_reduced.to_csv(filepath, index=False, encoding='utf_8_sig')
print(f'新表已保存到:{filepath}')