├── .gitignore ├── Answers ├── week1-challenge-01 │ └── read_challenge.py ├── week1-challenge-02 │ └── sql_challenge.py ├── week1-challenge-03 │ └── github_data.py ├── week1-challenge-04 │ └── shiyanlou_user.py ├── week1-challenge-05 │ ├── scrapy.cfg │ └── shiyanlou │ │ ├── __init__.py │ │ ├── items.py │ │ ├── middlewares.py │ │ ├── pipelines.py │ │ ├── settings.py │ │ └── spiders │ │ ├── __init__.py │ │ ├── github.py │ │ └── github_next_page.py ├── week2-challenge-01 │ └── titanic.py ├── week2-challenge-02 │ └── earthquake.py ├── week2-challenge-03 │ └── earthquake.py ├── week2-challenge-04 │ ├── carbon_dioxide.py │ └── carbon_dioxide_2.py ├── week2-challenge-05 │ └── carbon_gdp.py ├── week3-challenge-01 │ └── ols_matrix.py ├── week3-challenge-02 │ └── houseprice.py ├── week3-challenge-03 │ └── linear_regression.py ├── week3-challenge-04 │ └── 手写字符分类预测.ipynb ├── week3-challenge-05 │ └── 使用聚类压缩图像.ipynb ├── week4-challenge-01 │ └── banknote.py ├── week4-challenge-02 │ └── association.py ├── week4-challenge-03 │ └── google_stock.py ├── week4-challenge-04 │ └── production_index.py ├── week4-challenge-05 │ └── chengdu_pm25.py ├── week5-spiders-01 │ └── lianjia_spider.py └── week5-spiders-02 │ ├── create_sqlite_database.py │ ├── insert_database.py │ └── xiecheng_spider.py ├── Assignments ├── README.md ├── 🏅️dm01-stenphen-中国保险业过去五年基础数据分析.ipynb ├── 🏅️dm02-米竹314159-杭州互联网寒冬背景下的数据分析岗现状分析.ipynb ├── 🏅️dm04-Luo2019-链家成都市区挂牌二手房分析.ipynb ├── 🥈dm01-BellaG-上海历史天气数据分析预测.ipynb ├── 🥈dm02-linnecn-医学专业论坛的数据爬取和分析.ipynb ├── 🥈dm04-Yueyec-B-站番剧数据简单分析.ipynb └── 🥉dm01-hcccom-双色球历史数据统计预测.ipynb ├── LICENSE ├── Mindmaps ├── README.md ├── louplus-dm-week1.png ├── louplus-dm-week2.png ├── louplus-dm-week3.png ├── louplus-dm-week4.png └── louplus-dm-week5.png └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | .DS_Store 106 | -------------------------------------------------------------------------------- /Answers/week1-challenge-01/read_challenge.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | def convert(file): 4 | df = pd.read_json(file) 5 | df1000 = df[:1000] 6 | df1000.to_hdf('user_study.h5', key='data') -------------------------------------------------------------------------------- /Answers/week1-challenge-02/sql_challenge.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | import pandas as pd 3 | 4 | def count(file, user_id): 5 | 6 | sql_con = sqlite3.connect(file) 7 | sql_query = "SELECT * FROM data WHERE user_id == {}".format(user_id) 8 | df = pd.read_sql(sql_query, sql_con) 9 | 10 | if len(df)==0: 11 | return 0 12 | else: 13 | sum_minutes = df.minutes.sum() 14 | return sum_minutes -------------------------------------------------------------------------------- /Answers/week1-challenge-03/github_data.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import pandas as pd 3 | 4 | def issues(repo): 5 | url = "https://api.github.com/repos/{}/issues".format(repo) 6 | issues = requests.get(url) 7 | 8 | issues_list = [] 9 | for issue in issues.json(): 10 | issues_dict = {'number':issue['number'], 11 | 'title':issue['title'], 12 | 'user_name':issue['user']['login']} 13 | issues_list.append(issues_dict) 14 | 15 | issues_df = pd.DataFrame(issues_list) 16 | 17 | return issues_df 18 | 19 | issues("numpy/numpy") 20 | 21 | 22 | -------------------------------------------------------------------------------- /Answers/week1-challenge-04/shiyanlou_user.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from lxml import html 3 | 4 | 5 | def user_info(user_id): 6 | 7 | url = "https://www.lanqiao.cn/users/{}/".format(user_id) 8 | content = requests.get(url) 9 | 10 | if content.status_code == 200: 11 | tree = html.fromstring(content.text) 12 | # 首先选取所以 div 元素,要求其 class 属性中包含 name 字段 13 | # 再取 div 下的 span 14 | user_name = tree.xpath("//div[contains(@class, 'name')]/span/text()")[0].strip() 15 | user_level = tree.xpath("//div[contains(@class, 'name')]/span/text()")[1].strip()[1:] 16 | return user_name, int(user_level) 17 | else: 18 | user_name, user_level = (None, None) 19 | return user_name, user_level -------------------------------------------------------------------------------- /Answers/week1-challenge-05/scrapy.cfg: -------------------------------------------------------------------------------- 1 | # Automatically created by: scrapy startproject 2 | # 3 | # For more information about the [deploy] section see: 4 | # https://scrapyd.readthedocs.io/en/latest/deploy.html 5 | 6 | [settings] 7 | default = shiyanlou.settings 8 | 9 | [deploy] 10 | #url = http://localhost:6800/ 11 | project = shiyanlou 12 | -------------------------------------------------------------------------------- /Answers/week1-challenge-05/shiyanlou/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyanlou/louplus-dm/52764983b7080c3ca760e38c38c9a71cf0c2ed3e/Answers/week1-challenge-05/shiyanlou/__init__.py -------------------------------------------------------------------------------- /Answers/week1-challenge-05/shiyanlou/items.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Define here the models for your scraped items 4 | # 5 | # See documentation in: 6 | # https://doc.scrapy.org/en/latest/topics/items.html 7 | 8 | import scrapy 9 | 10 | 11 | class ShiyanlouItem(scrapy.Item): 12 | # define the fields for your item here like: 13 | # name = scrapy.Field() 14 | repo_name = scrapy.Field() # repo 名称 15 | update_time = scrapy.Field() # 更新时间 16 | -------------------------------------------------------------------------------- /Answers/week1-challenge-05/shiyanlou/middlewares.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Define here the models for your spider middleware 4 | # 5 | # See documentation in: 6 | # https://doc.scrapy.org/en/latest/topics/spider-middleware.html 7 | 8 | from scrapy import signals 9 | 10 | 11 | class ShiyanlouSpiderMiddleware(object): 12 | # Not all methods need to be defined. If a method is not defined, 13 | # scrapy acts as if the spider middleware does not modify the 14 | # passed objects. 15 | 16 | @classmethod 17 | def from_crawler(cls, crawler): 18 | # This method is used by Scrapy to create your spiders. 19 | s = cls() 20 | crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) 21 | return s 22 | 23 | def process_spider_input(self, response, spider): 24 | # Called for each response that goes through the spider 25 | # middleware and into the spider. 26 | 27 | # Should return None or raise an exception. 28 | return None 29 | 30 | def process_spider_output(self, response, result, spider): 31 | # Called with the results returned from the Spider, after 32 | # it has processed the response. 33 | 34 | # Must return an iterable of Request, dict or Item objects. 35 | for i in result: 36 | yield i 37 | 38 | def process_spider_exception(self, response, exception, spider): 39 | # Called when a spider or process_spider_input() method 40 | # (from other spider middleware) raises an exception. 41 | 42 | # Should return either None or an iterable of Response, dict 43 | # or Item objects. 44 | pass 45 | 46 | def process_start_requests(self, start_requests, spider): 47 | # Called with the start requests of the spider, and works 48 | # similarly to the process_spider_output() method, except 49 | # that it doesn’t have a response associated. 50 | 51 | # Must return only requests (not items). 52 | for r in start_requests: 53 | yield r 54 | 55 | def spider_opened(self, spider): 56 | spider.logger.info('Spider opened: %s' % spider.name) 57 | 58 | 59 | class ShiyanlouDownloaderMiddleware(object): 60 | # Not all methods need to be defined. If a method is not defined, 61 | # scrapy acts as if the downloader middleware does not modify the 62 | # passed objects. 63 | 64 | @classmethod 65 | def from_crawler(cls, crawler): 66 | # This method is used by Scrapy to create your spiders. 67 | s = cls() 68 | crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) 69 | return s 70 | 71 | def process_request(self, request, spider): 72 | # Called for each request that goes through the downloader 73 | # middleware. 74 | 75 | # Must either: 76 | # - return None: continue processing this request 77 | # - or return a Response object 78 | # - or return a Request object 79 | # - or raise IgnoreRequest: process_exception() methods of 80 | # installed downloader middleware will be called 81 | return None 82 | 83 | def process_response(self, request, response, spider): 84 | # Called with the response returned from the downloader. 85 | 86 | # Must either; 87 | # - return a Response object 88 | # - return a Request object 89 | # - or raise IgnoreRequest 90 | return response 91 | 92 | def process_exception(self, request, exception, spider): 93 | # Called when a download handler or a process_request() 94 | # (from other downloader middleware) raises an exception. 95 | 96 | # Must either: 97 | # - return None: continue processing this exception 98 | # - return a Response object: stops process_exception() chain 99 | # - return a Request object: stops process_exception() chain 100 | pass 101 | 102 | def spider_opened(self, spider): 103 | spider.logger.info('Spider opened: %s' % spider.name) 104 | -------------------------------------------------------------------------------- /Answers/week1-challenge-05/shiyanlou/pipelines.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Define your item pipelines here 4 | # 5 | # Don't forget to add your pipeline to the ITEM_PIPELINES setting 6 | # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html 7 | import pandas as pd 8 | 9 | class ShiyanlouPipeline(object): 10 | 11 | def process_item(self, item, spider): 12 | # 读取 item 数据 13 | repo_name = item['repo_name'] 14 | update_time = item['update_time'] 15 | # 每条数据组成临时 df_temp 16 | df_temp = pd.DataFrame([[repo_name, update_time]], columns=['repo_name', 'update_time']) 17 | # 将 df_temp 合并到 df 18 | self.df = self.df.append(df_temp, ignore_index=True).sort_values(by=['update_time'], ascending=False) 19 | 20 | return item 21 | 22 | #当爬虫启动时 23 | def open_spider(self, spider): 24 | # 新建一个带列名的空白 df 25 | self.df = pd.DataFrame(columns=['repo_name', 'update_time']) 26 | 27 | # 当爬虫关闭时 28 | def close_spider(self, spider): 29 | # 将 df 存储为 csv 文件 30 | pd.DataFrame.to_csv(self.df, "../shiyanlou_repo.csv") 31 | -------------------------------------------------------------------------------- /Answers/week1-challenge-05/shiyanlou/settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Scrapy settings for shiyanlou project 4 | # 5 | # For simplicity, this file contains only settings considered important or 6 | # commonly used. You can find more settings consulting the documentation: 7 | # 8 | # https://doc.scrapy.org/en/latest/topics/settings.html 9 | # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html 10 | # https://doc.scrapy.org/en/latest/topics/spider-middleware.html 11 | 12 | BOT_NAME = 'shiyanlou' 13 | 14 | SPIDER_MODULES = ['shiyanlou.spiders'] 15 | NEWSPIDER_MODULE = 'shiyanlou.spiders' 16 | 17 | 18 | # Crawl responsibly by identifying yourself (and your website) on the user-agent 19 | #USER_AGENT = 'shiyanlou (+http://www.yourdomain.com)' 20 | 21 | # Obey robots.txt rules 22 | ROBOTSTXT_OBEY = False 23 | 24 | # Configure maximum concurrent requests performed by Scrapy (default: 16) 25 | #CONCURRENT_REQUESTS = 32 26 | 27 | # Configure a delay for requests for the same website (default: 0) 28 | # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay 29 | # See also autothrottle settings and docs 30 | # DOWNLOAD_DELAY = 3 31 | # The download delay setting will honor only one of: 32 | #CONCURRENT_REQUESTS_PER_DOMAIN = 16 33 | #CONCURRENT_REQUESTS_PER_IP = 16 34 | 35 | # Disable cookies (enabled by default) 36 | #COOKIES_ENABLED = False 37 | 38 | # Disable Telnet Console (enabled by default) 39 | #TELNETCONSOLE_ENABLED = False 40 | 41 | # Override the default request headers: 42 | #DEFAULT_REQUEST_HEADERS = { 43 | # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 44 | # 'Accept-Language': 'en', 45 | #} 46 | 47 | # Enable or disable spider middlewares 48 | # See https://doc.scrapy.org/en/latest/topics/spider-middleware.html 49 | #SPIDER_MIDDLEWARES = { 50 | # 'shiyanlou.middlewares.ShiyanlouSpiderMiddleware': 543, 51 | #} 52 | 53 | # Enable or disable downloader middlewares 54 | # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html 55 | #DOWNLOADER_MIDDLEWARES = { 56 | # 'shiyanlou.middlewares.ShiyanlouDownloaderMiddleware': 543, 57 | #} 58 | 59 | # Enable or disable extensions 60 | # See https://doc.scrapy.org/en/latest/topics/extensions.html 61 | #EXTENSIONS = { 62 | # 'scrapy.extensions.telnet.TelnetConsole': None, 63 | #} 64 | 65 | # Configure item pipelines 66 | # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html 67 | ITEM_PIPELINES = { 68 | 'shiyanlou.pipelines.ShiyanlouPipeline': 300, 69 | } 70 | 71 | # Enable and configure the AutoThrottle extension (disabled by default) 72 | # See https://doc.scrapy.org/en/latest/topics/autothrottle.html 73 | #AUTOTHROTTLE_ENABLED = True 74 | # The initial download delay 75 | #AUTOTHROTTLE_START_DELAY = 5 76 | # The maximum download delay to be set in case of high latencies 77 | #AUTOTHROTTLE_MAX_DELAY = 60 78 | # The average number of requests Scrapy should be sending in parallel to 79 | # each remote server 80 | #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 81 | # Enable showing throttling stats for every response received: 82 | #AUTOTHROTTLE_DEBUG = False 83 | 84 | # Enable and configure HTTP caching (disabled by default) 85 | # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings 86 | #HTTPCACHE_ENABLED = True 87 | #HTTPCACHE_EXPIRATION_SECS = 0 88 | #HTTPCACHE_DIR = 'httpcache' 89 | #HTTPCACHE_IGNORE_HTTP_CODES = [] 90 | #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage' 91 | -------------------------------------------------------------------------------- /Answers/week1-challenge-05/shiyanlou/spiders/__init__.py: -------------------------------------------------------------------------------- 1 | # This package will contain the spiders of your Scrapy project 2 | # 3 | # Please refer to the documentation for information on how to create and manage 4 | # your spiders. 5 | -------------------------------------------------------------------------------- /Answers/week1-challenge-05/shiyanlou/spiders/github.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import scrapy 3 | from shiyanlou.items import ShiyanlouItem 4 | 5 | 6 | class GithubSpider(scrapy.Spider): 7 | name = 'github' 8 | allowed_domains = ['github.com'] 9 | 10 | @property 11 | def start_urls(self): 12 | url_temp = 'https://github.com/shiyanlou?after={}&tab=repositories' 13 | # 此参考会失效,请自行重新手动复制 after 参数 14 | after = [ 15 | '', 16 | 'Y3Vyc29yOnYyOpK5MjAxNy0wNi0wN1QwNjoxOTo1NyswODowMM4FkpYw', 17 | 'Y3Vyc29yOnYyOpK5MjAxNS0wMS0yNVQxMTozMTowNyswODowMM4Bxrsx', 18 | 'Y3Vyc29yOnYyOpK5MjAxNC0xMS0yMFQxMzowMzo1MiswODowMM4BjkvL', 19 | ] 20 | return (url_temp.format(i) for i in after) # 1-4 页 21 | 22 | def parse(self, response): 23 | repos = response.xpath('//li[@itemprop="owns"]') 24 | for repo in repos: 25 | item = ShiyanlouItem() 26 | item['repo_name'] = repo.xpath(".//a[@itemprop='name codeRepository']/text()").extract_first().strip() 27 | item['update_time'] = repo.xpath(".//relative-time/@datetime").extract_first() 28 | 29 | yield item -------------------------------------------------------------------------------- /Answers/week1-challenge-05/shiyanlou/spiders/github_next_page.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import scrapy 3 | from shiyanlou.items import ShiyanlouItem 4 | 5 | 6 | class GithubSpider(scrapy.Spider): 7 | name = 'github_next_page' 8 | allowed_domains = ['github.com'] 9 | 10 | @property 11 | def start_urls(self): 12 | return ('https://github.com/shiyanlou?tab=repositories', ) 13 | 14 | def parse(self, response): 15 | repos = response.xpath('//li[@itemprop="owns"]') 16 | for repo in repos: 17 | item = ShiyanlouItem() 18 | item['repo_name'] = repo.xpath(".//a[@itemprop='name codeRepository']/text()").extract_first().strip() 19 | item['update_time'] = repo.xpath(".//relative-time/@datetime").extract_first() 20 | 21 | yield item 22 | 23 | # 如果 Next 按钮没被禁用,那么表示有下一页 24 | spans = response.css('div.pagination span.disabled::text') 25 | if len(spans) == 0 or spans[-1].extract() != 'Next': 26 | next_url = response.css('div.paginate-container a:last-child::attr(href)').extract_first() 27 | yield response.follow(next_url, callback=self.parse) 28 | -------------------------------------------------------------------------------- /Answers/week2-challenge-01/titanic.py: -------------------------------------------------------------------------------- 1 | from matplotlib import pyplot as plt 2 | import seaborn as sns 3 | 4 | def plot(): 5 | df = sns.load_dataset("titanic") 6 | 7 | fig, axes = plt.subplots(ncols=3, nrows=1, figsize=(15,4)) 8 | 9 | sns.distplot(df.age.dropna(), ax=axes[0]) 10 | sns.countplot(x='sex', hue="alive", data=df, ax=axes[1]) 11 | sns.countplot(x="class", hue="alive", data=df, ax=axes[2]) 12 | 13 | return axes -------------------------------------------------------------------------------- /Answers/week2-challenge-02/earthquake.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | def clean(): 5 | # 读取据 6 | df = pd.read_csv("earthquake.csv") 7 | # 选择需保留列 8 | df1 = df[['time', 'latitude', 'longitude', 'depth', 'mag']] 9 | # 对 place 列使用分割,得到需要的 region 数据 10 | place = df.place.str.split(', ').tolist() 11 | region = [] 12 | for row in place: 13 | region.append(row[-1]) 14 | df2 = pd.DataFrame(region, columns=['region']) 15 | # 拼接数据 16 | df = pd.concat([df1, df2], axis=1) 17 | # 去除重复值 18 | df_clean = df.drop_duplicates().dropna() 19 | 20 | return df_clean -------------------------------------------------------------------------------- /Answers/week2-challenge-03/earthquake.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | def clean(): 5 | # 读取据 6 | df = pd.read_csv("earthquake.csv") 7 | # 选择需保留列 8 | df1 = df[['time', 'latitude', 'longitude', 'depth', 'mag']] 9 | # 对 place 列使用分割,得到需要的 region 数据 10 | place = df.place.str.split(', ').tolist() 11 | region = [] 12 | for row in place: 13 | region.append(row[-1]) 14 | df2 = pd.DataFrame(region, columns=['region']) 15 | # 拼接数据 16 | df = pd.concat([df1, df2], axis=1) 17 | # 去除重复值 18 | df_clean = df.drop_duplicates().dropna() 19 | 20 | return df_clean 21 | 22 | 23 | def mag_region(): 24 | # 加载清洁后数据 25 | df_clean = clean() 26 | # 数据离散化,注意开闭区间 27 | df_clean['mag'] = pd.cut(df_clean.mag, bins=[0, 2, 5, 7, 9, 15], right=False, labels=[ 28 | 'micro', 'light', 'strong', 'major', 'great']) 29 | 30 | print(df_clean) 31 | # 多索引分组聚合并计数 32 | df_group = df_clean.groupby(by=['mag', 'region']).count() 33 | # 重置索引并去除缺失值 34 | df_reindex = df_group.reset_index().dropna() 35 | # 按计数从大到小排序,并使用去除重复值的方法巧妙地保留下各地区最大值 36 | df_sort = df_reindex.sort_values( 37 | by='time', ascending=False).drop_duplicates(['mag']) 38 | # 按题目要求整理并重命名 39 | df_final = df_sort.set_index('mag')[['region', 'time']].rename( 40 | columns={"time": "times"}) 41 | # 按题目要求将计数处理成 int 类型 42 | df_final['times'] = df_final.times.astype('int') 43 | 44 | return df_final 45 | -------------------------------------------------------------------------------- /Answers/week2-challenge-04/carbon_dioxide.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | def data_clean(): 5 | '''data_clean() 函数用于数据清洁,大致步骤如下: 6 | 1. 统一设置国家代码为新索引 7 | 2. 去掉多余的数据列 8 | 3. 将不规范空值替换为 NaN,并进行填充 9 | ''' 10 | # 读取数据文件 11 | df_data = pd.read_excel("ClimateChange.xlsx", sheetname='Data') 12 | df_country = pd.read_excel("ClimateChange.xlsx", sheetname='Country') 13 | 14 | # 处理 data 数据表 15 | # 选取 EN.ATM.CO2E.KT 数据,并将国家代码设置为索引 16 | df_data_reindex = df_data[df_data['Series code']== 'EN.ATM.CO2E.KT'].set_index('Country code') 17 | # 剔除不必要的数据列 18 | df_data_drop = df_data_reindex.drop(labels=['Country name', 'Series code', 'Series name', 'SCALE', 'Decimals'], axis=1) 19 | # 将原数据集中不规范的空值替换为 NaN 方便填充 20 | df_data_nan = df_data_drop.replace({'..': pd.np.NaN}) 21 | # 对 NaN 空值进行向前和向后填充 22 | df_data_fill = df_data_nan.fillna(method='ffill', axis=1).fillna(method='bfill', axis=1) 23 | # 对填充后依旧全部为空值的数据行进行剔除 24 | df_data_dropna = df_data_fill.dropna(how='all') 25 | 26 | # 处理 Country 数据表 27 | # 将国家代码设置为索引 28 | df_country_reindex = pd.DataFrame(df_country).set_index('Country code') 29 | # 剔除不必要的数据列 30 | df_country_drop = df_country_reindex.drop(labels=['Capital city', 'Region', 'Lending category'], axis=1) 31 | 32 | # 合并数据表 33 | # 对 Data 和 Country 表按照索引进行合并 34 | df_combine = pd.concat([df_data_dropna, df_country_drop], axis=1) 35 | # 对合并后数据集进行求和得到各国排放总量 36 | df_combine['Sum emissions'] = df_combine[list(df_combine)[:-2]].sum(axis=1) 37 | # 对合并后存在空值的数据行进行剔除,得到清洁后的数据集 38 | df_clean = df_combine.dropna(thresh=10) 39 | 40 | return df_clean 41 | 42 | def co2(): 43 | '''co2() 函数用于数据统计,大致步骤如下: 44 | 1. 使用 groupby 按题目规则求和 45 | 2. 对数据进行排序并得到目标 DataFrame 46 | ''' 47 | # 读取清洁后数据 48 | df_clean = data_clean() 49 | 50 | # 按收入群体对数据进行求和 51 | sum_by_groups = df_clean.groupby('Income group')['Sum emissions'].sum() 52 | 53 | # 按要求整理 DataFrame 54 | item_high_list = [] 55 | item_low_list = [] 56 | 57 | for group_name in list(sum_by_groups.index): 58 | # 得到各收入群体最高排放量数据 59 | item_high = df_clean[df_clean['Income group'] == group_name].sort_values(by='Sum emissions', ascending=False).iloc[0] 60 | # 将最高排放量数据存入相应列表方便生成最终 DataFrame 61 | item_high_list.append((item_high['Income group'], item_high['Country name'], item_high['Sum emissions'])) 62 | # 得到各收入群体最低排放量数据 63 | item_low = df_clean[df_clean['Income group'] == group_name].sort_values(by='Sum emissions').iloc[0] 64 | # 将最低排放量数据存入相应列表方便生成最终 DataFrame 65 | item_low_list.append((item_low['Income group'], item_low['Country name'], item_low['Sum emissions'])) 66 | 67 | # 设置 DataFrame 标签 68 | high_labels = ['Income group', 'Highest emission country', 'Highest emissions'] 69 | low_labels = ['Income group', 'Lowest emission country', 'Lowest emissions'] 70 | 71 | # 生成并合并目标 DataFrame 72 | highest_df = pd.DataFrame.from_records(item_high_list, columns=high_labels).set_index('Income group') 73 | lowest_df = pd.DataFrame.from_records(item_low_list, columns=low_labels).set_index('Income group') 74 | 75 | results = pd.concat([sum_by_groups, highest_df, lowest_df], axis=1) 76 | 77 | return results -------------------------------------------------------------------------------- /Answers/week2-challenge-04/carbon_dioxide_2.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | def data_clean(): 5 | data = pd.read_excel("ClimateChange.xlsx", sheetname='Data') 6 | 7 | # 处理 data 数据表 # 选取 EN.ATM.CO2E.KT 数据,并将国家代码设置为索引 8 | data = data[data['Series code'] == 9 | 'EN.ATM.CO2E.KT'].set_index('Country code') 10 | # 剔除不必要的数据列 11 | data.drop(labels=['Country name', 'Series code', 12 | 'Series name', 'SCALE', 'Decimals'], axis=1, inplace=True) 13 | # 将原数据集中不规范的空值替换为 NaN 方便填充 14 | data.replace({'..': pd.np.NaN}, inplace=True) 15 | # 对 NaN 空值进行向前和向后填充 16 | data = data.fillna(method='ffill', axis=1).fillna(method='bfill', axis=1) 17 | # 对填充后依旧全部为空值的数据行进行剔除 18 | data.dropna(how='all', inplace=True) 19 | data['Sum emissions'] = data.sum(axis=1) 20 | data = data['Sum emissions'] 21 | 22 | # 处理 Country 数据表 23 | # 将国家代码设置为索引 24 | countries = pd.read_excel("ClimateChange.xlsx", sheetname='Country') 25 | countries.set_index('Country code', inplace=True) 26 | # 剔除不必要的数据列 27 | countries.drop(labels=['Capital city', 'Region', 28 | 'Lending category'], axis=1, inplace=True) 29 | 30 | # 合并数据表 31 | # 对 Data 和 Country 表按照索引进行合并 32 | return pd.concat([data, countries], axis=1) 33 | 34 | 35 | def co2(): 36 | '''co2() 函数用于数据统计,大致步骤如下: 37 | 1. 使用 grouby 按题目规则求和 38 | 2. 对数据进行排序并得到目标 DataFrame 39 | ''' 40 | # 读取清洁后数据 41 | df = data_clean() 42 | 43 | # 按收入群体对数据进行求和 44 | df_sum = df.groupby('Income group').sum() 45 | 46 | df_max = df.sort_values(by='Sum emissions', ascending=False).groupby( 47 | 'Income group').head(1).set_index('Income group') 48 | df_max.columns = ['Highest emissions', 'Highest emission country'] 49 | df_max = df_max.reindex( 50 | columns=['Highest emission country', 'Highest emissions']) 51 | 52 | df_min = df.sort_values(by='Sum emissions').groupby( 53 | 'Income group').head(1).set_index('Income group') 54 | df_min.columns = ['Lowest emissions', 'Lowest emission country'] 55 | df_min = df_min.reindex( 56 | columns=['Lowest emission country', 'Lowest emissions']) 57 | 58 | result = pd.concat([df_sum, df_max, df_min], axis=1) 59 | 60 | return result -------------------------------------------------------------------------------- /Answers/week2-challenge-05/carbon_gdp.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | from matplotlib import pyplot as plt 4 | 5 | 6 | def data_clean(): 7 | '''data_clean() 函数用于数据清洁,大致步骤如下: 8 | 1. 统一设置国家代码为新索引 9 | 2. 去掉多余的数据列 10 | 3. 将不规范空值替换为 NaN,并进行填充 11 | ''' 12 | # 读取数据 13 | df_data = pd.read_excel("ClimateChange.xlsx", sheetname='Data') 14 | 15 | # 选择数据 16 | df_co2 = df_data[df_data['Series code'] == 17 | 'EN.ATM.CO2E.KT'].set_index('Country code') 18 | df_gdp = df_data[df_data['Series code'] == 19 | 'NY.GDP.MKTP.CD'].set_index('Country code') 20 | 21 | # 缺失值替换 22 | df_co2_nan = df_co2.replace({'..': pd.np.NaN}) 23 | df_gdp_nan = df_gdp.replace({'..': pd.np.NaN}) 24 | 25 | # 缺失值填充 26 | df_co2_fill = df_co2_nan.iloc[:, 5:].fillna( 27 | method='ffill', axis=1).fillna(method='bfill', axis=1) 28 | df_gdp_fill = df_gdp_nan.iloc[:, 5:].fillna( 29 | method='ffill', axis=1).fillna(method='bfill', axis=1) 30 | 31 | # 数据合并 32 | df_co2_fill['CO2-SUM'] = df_co2_fill.sum(axis=1) 33 | df_gdp_fill['GDP-SUM'] = df_gdp_fill.sum(axis=1) 34 | df_merge = pd.concat([df_co2_fill['CO2-SUM'], df_gdp_fill['GDP-SUM']], axis=1) 35 | 36 | # 缺失数据填充为 0 37 | df_merge_fill = df_merge.fillna(value=0) 38 | 39 | return df_merge_fill 40 | 41 | 42 | def co2_gdp_plot(): 43 | '''co2_gdp_plot() 函数用于数据整理和绘图,大致步骤如下: 44 | 1. 数据归一化 45 | 2. 得到需要返回的数据 46 | 3. 绘图 47 | ''' 48 | # 读取数据 49 | df_clean = data_clean() 50 | 51 | # 数据归一化处理 52 | df_max_min = (df_clean - df_clean.min()) / (df_clean.max() - df_clean.min()) 53 | 54 | # 获取中国归一化后的 CO2 和 GDP 数据 55 | china = [] 56 | for i in df_max_min[df_max_min.index == 'CHN'].values: 57 | china.extend(np.round(i, 3).tolist()) 58 | 59 | # 获取 5 个常任理事国标签及对应的坐标刻度 60 | countries_labels = ['USA', 'CHN', 'FRA', 'RUS', 'GBR'] 61 | # 获取国家标签作为刻度标签 62 | sticks_labels = [] 63 | # 获取相应国家序号对应着刻度坐标 64 | labels_position = [] 65 | 66 | for i in range(len(df_max_min)): 67 | if df_max_min.index[i] in countries_labels: 68 | sticks_labels.append(df_max_min.index[i]) 69 | labels_position.append(i) 70 | 71 | # 对数据进行绘图 72 | fig, axes = plt.subplots() 73 | df_max_min.plot( 74 | kind='line', 75 | title='GDP-CO2', 76 | ax=axes 77 | ) 78 | plt.xlabel("Countries") 79 | plt.ylabel("Values") 80 | # 绘制 5 大常任理事国坐标刻度标签 81 | plt.xticks(labels_position, sticks_labels, rotation='vertical') 82 | plt.show() 83 | 84 | return axes, china -------------------------------------------------------------------------------- /Answers/week3-challenge-01/ols_matrix.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | 5 | def caculate_w(): 6 | 7 | # 读取数据集 8 | df = pd.read_csv("nyc-east-river-bicycle-counts.csv", index_col=0) 9 | 10 | # 处理自变量 11 | x = df['Brooklyn Bridge'].values 12 | x = x.reshape(len(x), 1) # 添加截距项系数 13 | x = np.matrix(np.concatenate((np.ones_like(x), x), axis=1)) 14 | 15 | # 处理因变量 16 | y = df['Manhattan Bridge'].values 17 | y = np.matrix(y.reshape(len(y), 1)) 18 | 19 | # 使用矩阵方法计算 20 | W = (x.T * x).I * x.T * y 21 | b = round(float(W[0]), 2) 22 | w = round(float(W[1]), 2) 23 | 24 | return w, b 25 | -------------------------------------------------------------------------------- /Answers/week3-challenge-02/houseprice.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from sklearn.preprocessing import PolynomialFeatures 4 | from sklearn.linear_model import LinearRegression 5 | from sklearn.metrics import mean_absolute_error 6 | from sklearn.model_selection import train_test_split 7 | 8 | 9 | def beijing(n): 10 | 11 | # 读取数据,去除重复值,无空值 12 | df = pd.read_csv("beijing_house_price.csv") 13 | df = df.drop_duplicates() 14 | # df = df[['公交', '写字楼', '医院', '商场', '地铁', '学校', '建造时间', '楼层', '面积', '每平米价格']] 15 | df = df.iloc[:, [0, 1, 2, 3, 4, 5, 7, 9, 11, 10]] # 线上环境中文输入不方便 16 | 17 | # 计算特征与目标值相关性系数,并保留前 3 个特征 18 | pearson = np.abs(df.corr(method='pearson').iloc[-1]) 19 | pearson_max = pearson.sort_values(ascending=False)[1:4] 20 | features_names = pearson_max.index.values 21 | features = df[features_names] 22 | # target = df['每平米价格'] 23 | target = df.iloc[:, [9]] 24 | 25 | # 切分训练和测试数据 26 | X_train, X_test, y_train, y_test = train_test_split( 27 | features, target, test_size=0.3, random_state=10) 28 | 29 | # 多项式特征处理 30 | poly_features = PolynomialFeatures(degree=n) 31 | X_train_features = poly_features.fit_transform(X_train) 32 | X_test_features = poly_features.fit_transform(X_test) 33 | 34 | # 建立线性回归模型 35 | model = LinearRegression() 36 | model.fit(X_train_features, y_train) 37 | y_pred = model.predict(X_test_features) 38 | 39 | # 计算平均绝对误差 40 | mae = mean_absolute_error(y_test, y_pred) 41 | 42 | return mae 43 | -------------------------------------------------------------------------------- /Answers/week3-challenge-03/linear_regression.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | 5 | def gradient_descent(): 6 | # 读取数据集 7 | df = pd.read_csv("nyc-east-river-bicycle-counts.csv", index_col=0) 8 | # 读取自变量 9 | x = df['Brooklyn Bridge'].values 10 | # 读取因变量 11 | y = df['Manhattan Bridge'].values 12 | 13 | w = 0 # 初始参数为 0 14 | b = 0 # 初始参数为 0 15 | lr = 0.000000001 # 学习率 16 | num_iter = 1000 # 迭代次数 17 | for i in range(num_iter): # 梯度下降迭代 18 | # 计算近似值 19 | y_hat = (w * x) + b 20 | # 计算参数对应梯度 21 | w_gradient = -(2/len(x)) * sum(x * (y - y_hat)) 22 | b_gradient = -(2/len(x)) * sum(y - y_hat) 23 | # 根据梯度更新参数 24 | w -= lr * w_gradient 25 | b -= lr * b_gradient 26 | 27 | return w, b 28 | -------------------------------------------------------------------------------- /Answers/week3-challenge-04/手写字符分类预测.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "# 手写字符分类预测" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "---" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "**以下内容仅保留挑战代码部分,挑战全文请到原课程查看。**" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "---" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "**挑战:使用 `1x5` 的子图样式绘制 Digits 数据集前 `5` 个手写字符的图像。**" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": null, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "### 代码开始 ### (3~5 行代码)\n", 47 | "fig, axes = plt.subplots(1, 5, figsize=(12,4))\n", 48 | "for i, image in enumerate(digits.images[:5]):\n", 49 | " axes[i].imshow(image, cmap=plt.cm.gray_r)\n", 50 | "### 代码结束 ###" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "---" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "**挑战:使用 `train_test_split()` 将数据集切分为 80%(训练集) 和 20%(测试集) 两部分。**" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": null, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "### 代码开始 ### (≈ 2 行代码)\n", 74 | "from sklearn.model_selection import train_test_split\n", 75 | "\n", 76 | "train_x, test_x, train_y, test_y = train_test_split(digits.data, digits.target, test_size=0.2, random_state=30)\n", 77 | "### 代码结束 ###" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "---" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "**挑战:使用 `MLPClassifier()` 搭建神经网络结构,并训练手写字符识别模型,最后得到在测试集上的预测准确率。**" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "from sklearn.neural_network import MLPClassifier\n", 101 | "from sklearn.metrics import accuracy_score\n", 102 | "\n", 103 | "def mpl():\n", 104 | " \"\"\"\n", 105 | " 参数:无\n", 106 | "\n", 107 | " 返回:\n", 108 | " model -- 人工神经网络模型\n", 109 | " score -- 测试集上的预测准确率\n", 110 | " \"\"\"\n", 111 | " ### 代码开始 ### (≈ 2 行代码)\n", 112 | " model = MLPClassifier(\n", 113 | " hidden_layer_sizes=(100, 50),\n", 114 | " activation='relu',\n", 115 | " solver='sgd',\n", 116 | " learning_rate_init=0.02,\n", 117 | " learning_rate='constant',\n", 118 | " max_iter=100,\n", 119 | " random_state=1\n", 120 | " )\n", 121 | "\n", 122 | " model.fit(train_x, train_y)\n", 123 | " score = accuracy_score(test_y, model.predict(test_x))\n", 124 | " ### 代码结束 ###\n", 125 | " return model, score" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "---" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "" 140 | ] 141 | } 142 | ], 143 | "metadata": { 144 | "kernelspec": { 145 | "display_name": "Python 3", 146 | "language": "python", 147 | "name": "python3" 148 | }, 149 | "language_info": { 150 | "codemirror_mode": { 151 | "name": "ipython", 152 | "version": 3 153 | }, 154 | "file_extension": ".py", 155 | "mimetype": "text/x-python", 156 | "name": "python", 157 | "nbconvert_exporter": "python", 158 | "pygments_lexer": "ipython3", 159 | "version": "3.7.0" 160 | } 161 | }, 162 | "nbformat": 4, 163 | "nbformat_minor": 2 164 | } 165 | -------------------------------------------------------------------------------- /Answers/week3-challenge-05/使用聚类压缩图像.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "# 使用聚类压缩图像" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "---" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "**以下内容仅保留挑战代码部分,挑战全文请到原课程查看。**" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "---" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "**挑战:将形状为 $(516, 819, 3)$ 的数据转换为 $(422604, 3)$ 形状的数据。**" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": null, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "\"\"\"数据格式变换\n", 47 | "\"\"\"\n", 48 | "### 代码开始 ###(≈ 1 行代码)\n", 49 | "data = chengdu.reshape(516 * 819, 3)\n", 50 | "### 代码结束 ###" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "---" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "**挑战:计算 `422604` 个像素点中种类的个数。**" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": null, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "\"\"\"计算像素点种类个数\n", 74 | "\"\"\"\n", 75 | "def get_variety(data):\n", 76 | " \"\"\"\n", 77 | " 参数:\n", 78 | " 预处理后像素点集合\n", 79 | "\n", 80 | " 返回:\n", 81 | " num_variety -- 像素点种类个数\n", 82 | " \"\"\"\n", 83 | "\n", 84 | " ### 代码开始 ### (≈ 3 行代码)\n", 85 | " temp=data.tolist()\n", 86 | " num_variety=len(set([tuple(t) for t in temp]))\n", 87 | " ### 代码结束 ###\n", 88 | " \n", 89 | " return num_variety" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "---" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "**挑战:使用 Mini Batch K-Means 聚类方法对像素点进行聚类,并用每一个中心的像素点代替属于该类别的像素点。**" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "from sklearn.cluster import MiniBatchKMeans\n", 113 | "\n", 114 | "### 代码开始 ###(≈ 4 行代码)\n", 115 | "model = MiniBatchKMeans(10)\n", 116 | "model.fit(data)\n", 117 | "predict=model.predict(data)\n", 118 | "### 代码结束 ###\n", 119 | "\n", 120 | "new_colors = model.cluster_centers_[predict]" 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "metadata": {}, 126 | "source": [ 127 | "---" 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "metadata": {}, 133 | "source": [ 134 | "**挑战:将聚类后并替换为类别中心点值的像素点,变换为数据处理前的格式,并绘制出图片进行对比展示。**" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": null, 140 | "metadata": {}, 141 | "outputs": [], 142 | "source": [ 143 | "fig, ax = plt.subplots(1, 2, figsize=(16, 6))\n", 144 | "\n", 145 | "### 代码开始 ###(≈ 3 行代码)\n", 146 | "new_chengdu = new_colors.reshape(chengdu.shape)\n", 147 | "ax[0].imshow(chengdu)\n", 148 | "ax[1].imshow(new_chengdu)\n", 149 | "### 代码结束 ###" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "---" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "" 164 | ] 165 | } 166 | ], 167 | "metadata": { 168 | "kernelspec": { 169 | "display_name": "Python 3", 170 | "language": "python", 171 | "name": "python3" 172 | }, 173 | "language_info": { 174 | "codemirror_mode": { 175 | "name": "ipython", 176 | "version": 3 177 | }, 178 | "file_extension": ".py", 179 | "mimetype": "text/x-python", 180 | "name": "python", 181 | "nbconvert_exporter": "python", 182 | "pygments_lexer": "ipython3", 183 | "version": "3.7.0" 184 | } 185 | }, 186 | "nbformat": 4, 187 | "nbformat_minor": 2 188 | } 189 | -------------------------------------------------------------------------------- /Answers/week4-challenge-01/banknote.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | from sklearn.svm import SVC 4 | 5 | def identify(): 6 | 7 | df_train = pd.read_csv("banknote_train.csv") 8 | df_test = pd.read_csv("banknote_test.csv") 9 | 10 | model = SVC(gamma='auto') 11 | model.fit(df_train.iloc[:, :-1], df_train['class']) 12 | df_test['class'] = model.predict(df_test) 13 | 14 | return df_test -------------------------------------------------------------------------------- /Answers/week4-challenge-02/association.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from mlxtend.preprocessing import TransactionEncoder 3 | from mlxtend.frequent_patterns import apriori 4 | from mlxtend.frequent_patterns import association_rules as rules 5 | 6 | def rule(): 7 | 8 | df = pd.read_csv("shopping_data.csv", header=None) 9 | dataset = df.stack().groupby(level=0).apply(list).tolist() 10 | 11 | te = TransactionEncoder() # 定义模型 12 | te_ary = te.fit_transform(dataset) # 转换数据集 13 | df = pd.DataFrame(te_ary, columns=te.columns_) # 将数组处理为 DataFrame 14 | 15 | frequent_itemsets = apriori(df, min_support=0.05, use_colnames=True) 16 | association_rules = rules(frequent_itemsets, metric="confidence", min_threshold=0.2) # 置信度阈值为 0.1 17 | 18 | return frequent_itemsets, association_rules -------------------------------------------------------------------------------- /Answers/week4-challenge-03/google_stock.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | def quarter_volume(): 5 | df = pd.read_csv("GOOGL.csv", index_col=0) 6 | df.index = pd.to_datetime(df.index) 7 | df = df.resample('Q').agg({"Open": 'mean', "High": 'mean', "Low": 'mean', 8 | "Close": 'mean', "Adj Close": 'mean', "Volume": 'sum'}) 9 | df = df.sort_values(by='Volume', ascending=False) 10 | return df -------------------------------------------------------------------------------- /Answers/week4-challenge-04/production_index.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from statsmodels.tsa.stattools import arma_order_select_ic 3 | 4 | 5 | def arima(): 6 | df = pd.read_csv("agriculture.csv", index_col=0) 7 | diff = df.diff().dropna() 8 | p, q = arma_order_select_ic(diff, ic='aic')['aic_min_order'] # AIC 9 | d = 1 10 | return p, d, q 11 | -------------------------------------------------------------------------------- /Answers/week4-challenge-05/chengdu_pm25.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from fbprophet import Prophet 3 | 4 | 5 | def additive(): 6 | df = pd.read_csv("Chengdu_HourlyPM25.csv") 7 | df_nan = df.replace({-999: pd.np.NaN}) 8 | df = df_nan.fillna(method='ffill').fillna(method='bfill') 9 | 10 | df.index = pd.to_datetime(df['Date (LST)']) 11 | df = df.resample('D').mean() 12 | df = df.reset_index() 13 | df.rename(columns={'Date (LST)': 'ds', 'Value': 'y'}, inplace=True) 14 | 15 | m = Prophet() # 创建加法模型 16 | m.fit(df) 17 | 18 | future = m.make_future_dataframe(periods=365, freq='D') # 生成预测序列 19 | forecast = m.predict(future) # 预测 20 | # 仅保留预测值和相应的置信区间 21 | forecast = forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']] 22 | forecast = forecast.set_index('ds')['2017-01-01':] 23 | 24 | forecast.to_csv("forecast.csv") # 存为数据文件 25 | 26 | return forecast 27 | 28 | additive() -------------------------------------------------------------------------------- /Answers/week5-spiders-01/lianjia_spider.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from bs4 import BeautifulSoup 3 | import time 4 | from tqdm import tqdm 5 | import re 6 | import sqlite3 7 | import pandas as pd 8 | 9 | ''' 10 | 爬虫代码分为三步: 11 | 1. 爬取房屋 id 12 | 2. 根据房屋 id 组合 url,然后依次爬取房屋的具体界面获取信息 13 | 3. 保存到本地 14 | ''' 15 | 16 | base_url = 'https://sh.lianjia.com/zufang/' 17 | test_url = 'https://sh.lianjia.com/zufang/pg1/' 18 | headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'} 19 | 20 | # 获取一页的房屋列表,具体为房屋的 id,例如 107100610451 21 | def getHouseURLList(page_url): 22 | try: 23 | r = requests.get(page_url, timeout=5, headers=headers) 24 | if r.status_code==403: 25 | print('访问被拒,请稍后再试') 26 | except requests.exceptions.Timeout: 27 | # 请求超时,返回无效数据 28 | return None 29 | content = r.content 30 | soup = BeautifulSoup(content) 31 | result_list = list(soup.select('#house-lst')[0].children) 32 | return_list = [] 33 | for result in result_list: 34 | return_list.append(result['data-id']) 35 | return return_list 36 | 37 | # 示例 38 | # return_list = getHouseURLList(test_url) 39 | 40 | # 房屋 id 41 | data_id_list = [] 42 | 43 | # 多走几轮,以获得更全的数据 44 | for _ in range(1): 45 | # for i in tqdm(range(1, 101)): 46 | for i in tqdm(range(1, 2)): 47 | page_url = base_url+'pg{}/'.format(i) 48 | return_list = getHouseURLList(page_url) 49 | if not return_list: 50 | time.sleep(10) 51 | continue 52 | data_id_list.extend(return_list) 53 | 54 | # 去除重复数据 55 | data_id_list = list(set(data_id_list)) 56 | 57 | # 写入本地文件,保存房屋 id 58 | with open('house_id_list.txt', 'w') as f: 59 | f.write('\n'.join(data_id_list)) 60 | 61 | 62 | # 清理面积 63 | def clean_str(s): 64 | # 去除中文 65 | re.sub(r'[^\x00-\x7f]', '', s) 66 | new_s = [] 67 | for c in s: 68 | # 遇到非数字则舍去 69 | if c.isdigit(): new_s.append(c) 70 | else: break 71 | return ''.join(new_s) 72 | 73 | # 定义一个类保存数据 74 | class Room(object): 75 | def __init__(self, url): 76 | self.done = False 77 | self.area = 0 78 | self.url = url 79 | self.price = '' 80 | self.isRemoved = '' 81 | self.special_label = '' 82 | self.title = '' 83 | self.floor = '' 84 | self.is_near_subway = '' 85 | self.publish_time = '' 86 | self.rooms = '' 87 | self.toilet = '' 88 | self.halls = '' 89 | self.rent_way = '' 90 | self.location = '' 91 | 92 | # 房屋面积 93 | def setArea(self, area): 94 | self.area = float(clean_str(area)) 95 | 96 | # 价格 97 | def setPrice(self, price): 98 | self.price = price 99 | 100 | # 是否下架 101 | def setIsRemoved(self, isRemoved): 102 | self.isRemoved = isRemoved 103 | 104 | # 是否精装修 105 | def setSpecialLabel(self, special_label): 106 | self.special_label = special_label 107 | 108 | # 户型: 房间数量,房间,大厅,卫生间; 出租方式: 整租、合租 109 | def setType(self, type): 110 | tmp = type.split() 111 | if len(tmp) == 1: 112 | room_count = tmp[0] 113 | rent_way = '暂无信息' 114 | else: 115 | room_count, rent_way = tmp 116 | room_count = re.sub(r'[^\x00-\x7f]', ' ', room_count).strip().split() 117 | room_count = list(map(int, room_count)) 118 | 119 | # 部分房屋无卫生间或客厅 120 | if len(room_count) < 3: 121 | for i in range(3 - len(room_count)): 122 | room_count.append(0) 123 | 124 | self.rooms = room_count[0] 125 | self.halls = room_count[1] 126 | self.toilet = room_count[2] 127 | self.rent_way = rent_way 128 | 129 | # 位置 130 | def setLocation(self, location): 131 | self.location = location 132 | 133 | # 是否靠近地铁 134 | def setSubway(self, is_near_subway): 135 | self.is_near_subway = is_near_subway 136 | 137 | # 朝向 138 | def setDirection(self, direction): 139 | self.direction = direction 140 | 141 | # 楼层 142 | def setFloor(self, floor): 143 | self.floor = floor 144 | 145 | # 发布时间 146 | def setPublishTime(self, publish_time): 147 | self.publish_time = publish_time 148 | 149 | # 房屋标题 150 | def setTitle(self, title): 151 | self.title = title 152 | 153 | # 房屋链接 154 | def setURL(self, URL): 155 | self.url = URL 156 | 157 | # 是否爬取成功 158 | def setDone(self, done): 159 | self.done = done 160 | 161 | def __repr__(self): 162 | return str(self.__dict__) 163 | 164 | # 给定 url 获取房屋信息 165 | def getRoom(url): 166 | room = Room(url) 167 | try: 168 | r = requests.get(url, timeout=5, headers=headers) 169 | if r.status_code==403: 170 | print('访问被拒,请稍后再试') 171 | except requests.exceptions.Timeout: 172 | time.sleep(2) 173 | print('timeout') 174 | return Room('invalid') 175 | content = r.content.decode() 176 | 177 | soup = BeautifulSoup(content, features='lxml') 178 | 179 | title = soup.find('h1', class_='main').text 180 | room.setTitle(title) 181 | 182 | price_div = soup.find('div', class_='price') 183 | price_list = list(price_div.stripped_strings) # ['9000', '元/月', '精装修'] 184 | price = ''.join(price_list[:2]) 185 | room.setPrice(price) 186 | 187 | special_label = ' '.join(price_list[2:]) if len(price_list)>2 else '无' 188 | room.setSpecialLabel(special_label) 189 | isRemoved = '已下架' if price_div['class'][1] == 'isRemove' else '正在出租' 190 | room.setIsRemoved(isRemoved) 191 | 192 | room_info = soup.find('div', class_='zf-room') 193 | room_info_list = list(room_info.stripped_strings) 194 | 195 | location = "{} {} {}".format(room_info_list[15], room_info_list[16], room_info_list[11]) 196 | room.setLocation(location) 197 | room.setPublishTime(room_info_list[-1]) 198 | room.setArea(room_info_list[1]) 199 | room.setType(room_info_list[3]) # 4室2厅3卫; 200 | room.setFloor(room_info_list[5]) 201 | room.setDirection(room_info_list[7]) 202 | room.setSubway(room_info_list[9]) 203 | 204 | room.setDone(True) 205 | 206 | return room 207 | 208 | # 连接数据库 209 | conn = sqlite3.connect('lianjia.db') 210 | 211 | cursor = conn.cursor() 212 | # 创建表,如果已创建,则删除下面这行 213 | cursor.execute(''' 214 | CREATE TABLE ROOM( 215 | url VARCHAR(1000) PRIMARY KEY, 216 | price Double, 217 | area Double, 218 | isRemoved VARCHAR(1000), 219 | special_label VARCHAR(1000), 220 | rooms INT, 221 | halls INT, 222 | toilet INT, 223 | rent_way INT, 224 | location VARCHAR(1000), 225 | is_near_subway VARCHAR(1000), 226 | direction VARCHAR(1000), 227 | floor VARCHAR(1000), 228 | publish_time VARCHAR(1000), 229 | title VARCHAR(1000) 230 | ) 231 | ''') 232 | 233 | SELECT_COMMAND = "select * from ROOM where url='{}';" 234 | INSERT_COMMAND = "insert into ROOM(url, price, area, isRemoved, \ 235 | special_label, rooms, halls, toilet, rent_way, \ 236 | location, is_near_subway, direction, floor, publish_time, title) \ 237 | values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);" 238 | 239 | # 根据上面爬取到的房屋 ID 组合生成 url,然后依次爬取 240 | def getAllHouseInfo(file_path): 241 | base_url = 'https://sh.lianjia.com/zufang/{}.html' 242 | with open(file_path) as f: 243 | lines = f.readlines() 244 | 245 | urls = [base_url.format(line.strip('\n')) for line in lines] 246 | for url in tqdm(urls): 247 | cursor = conn.cursor() 248 | cursor.execute(SELECT_COMMAND.format(url)) 249 | if len(cursor.fetchall()) != 0: 250 | continue 251 | cursor.close() 252 | # 如果失败,最多尝试 5 次 253 | count = 0 254 | while count < 5: 255 | room = getRoom(url) 256 | if room.done: 257 | break 258 | count += 1 259 | if count == 5: 260 | continue 261 | 262 | # 插入数据库 263 | cursor = conn.cursor() 264 | cursor.execute(INSERT_COMMAND, 265 | (room.url, room.price, room.area, room.isRemoved, room.special_label, 266 | room.rooms, room.halls, room.toilet, room.rent_way, room.location, room.is_near_subway, 267 | room.direction, room.floor, room.publish_time, room.title)) 268 | cursor.close() 269 | conn.commit() 270 | if cursor.rowcount != 1: 271 | print('插入错误') 272 | 273 | 274 | getAllHouseInfo('house_id_list.txt') 275 | 276 | csv_path = 'lianjia.csv' 277 | 278 | cursor = conn.cursor() 279 | 280 | # 保存到本地 csv 文件 281 | cursor.execute('SELECT * FROM ROOM') 282 | 283 | data = cursor.fetchall() 284 | data = list(map(list, data)) 285 | name_attribute = ['url', 'price', 'area', 'state', 'label', 'rooms', 'halls', 'toilets', 'rentway', 'location', 286 | 'subway', 'direction', 'floor', 'publishtime', 'title'] 287 | data_frame =pd.DataFrame(columns=name_attribute,data=data) 288 | data_frame.to_csv(csv_path, encoding='utf_8_sig') 289 | conn.close() -------------------------------------------------------------------------------- /Answers/week5-spiders-02/create_sqlite_database.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | 4 | # 创建携程数据库 5 | conn = sqlite3.connect('xiecheng.db') 6 | 7 | # 创建一个包含机票信息的表 8 | # 分别是 公司名、出发时间、到达时间、出发机场、到达机场、飞机类型、准点率、飞机编号、价格、日期 9 | CREATE_COMMAND1 = ''' 10 | CREATE table AIRPLANE ( 11 | company_name varchar(1000), 12 | start_time varchar(1000), 13 | arrival_time varchar(1000), 14 | start_airport varchar(1000), 15 | arrival_airport varchar(1000), 16 | airpane_type varchar(1000), 17 | ontime_rate float, 18 | airpane_number varchar(1000), 19 | price float, 20 | date varchar(1000) 21 | ); 22 | ''' 23 | 24 | # 选择预计,根据飞机编号、日期、出发时间选出需要的机票信息 25 | SELECT_COMMAND = ''' 26 | select * from AIRPLANE where airpane_number=? and date=? and start_time=?; 27 | ''' 28 | 29 | # 插入新的数据 30 | INSERT_COMMAND1 = ''' 31 | insert into AIRPLANE values(?,?,?,?,?,?,?,?,?,?); 32 | ''' 33 | 34 | # 创建一个最低价格的表,包含出发城市、到达城市、日期、最低价格 35 | CREATE_COMMAND2 = ''' 36 | CREATE table LOWEST_PRICE ( 37 | start_city varchar(1000), 38 | arrival_city varchar(1000), 39 | date varchar(1000), 40 | price float 41 | ); 42 | ''' 43 | 44 | # 插入数据 45 | INSERT_COMMAND2 = ''' 46 | insert into LOWEST_PRICE values(?,?,?,?); 47 | ''' 48 | 49 | # 创建表 50 | cursor = conn.cursor() 51 | cursor.execute(CREATE_COMMAND1) 52 | cursor.close() 53 | cursor = conn.cursor() 54 | cursor.execute(CREATE_COMMAND2) 55 | cursor.close() 56 | -------------------------------------------------------------------------------- /Answers/week5-spiders-02/insert_database.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import pandas as pd 3 | 4 | 5 | base = datetime.date(2018, 10, 30) 6 | numdays = 80 7 | 8 | # 所有的十月三十号以后的八十天的 list 9 | date_list = [base + datetime.timedelta(days=x) for x in range(0, numdays)] 10 | 11 | # 获取从 start 到 dest 的数据并插入数据库中 12 | def getTickets(start, dest, driver, date_list, conn): 13 | cursor = conn.cursor() 14 | name_attribute = [] 15 | for one_day in tqdm_notebook(date_list): 16 | # 获取数据 17 | tmp = get_ticket_info(start, dest, str(one_day), driver) 18 | for x in tmp: 19 | result = cursor.execute( 20 | SELECT_COMMAND, (x[-2], str(one_day), x[1])).fetchall() 21 | x.append(str(one_day)) 22 | if len(result) == 0: 23 | # 如果没有爬取则插入数据库 24 | cursor.execute(INSERT_COMMAND1, x) 25 | conn.commit() 26 | cursor.close() 27 | 28 | 29 | # 成都到上海和上海到成都 30 | getTickets('CTU', 'SHA', driver, date_list, conn) 31 | getTickets('SHA', 'CTU', driver, date_list, conn) 32 | -------------------------------------------------------------------------------- /Answers/week5-spiders-02/xiecheng_spider.py: -------------------------------------------------------------------------------- 1 | # 使用 BeautifulSoup 进行解析 2 | from bs4 import BeautifulSoup 3 | from selenium import webdriver 4 | from selenium.common.exceptions import TimeoutException 5 | import time 6 | from selenium.webdriver.chrome.options import Options 7 | import re 8 | from selenium.webdriver.common.proxy import Proxy, ProxyType 9 | 10 | 11 | ''' 12 | dstation: 出发城市代码 13 | astation: 到达城市代码 14 | date: 出发日期,形如 2018-10-30 15 | driver: 创建的 webdriver 16 | ''' 17 | def get_ticket_info(dstation, astation, date, driver): 18 | url = "http://flights.ctrip.com/booking/%s-%s-day-1.html?DDate1=%s" % ( 19 | dstation, astation, date) 20 | # 一直尝试到成功 21 | while True: 22 | try: 23 | driver.get(url) 24 | break 25 | except TimeoutException as e: 26 | pass 27 | # 等待页面加载出来 28 | time.sleep(2) 29 | 30 | # webdriver 执行 js 语句滑动窗口,一直滑动到底部 31 | initial_pagesource = driver.page_source 32 | while True: 33 | # 滑到页面底部,暂停 0.1 秒是为了等待页面刷新出结果 34 | driver.execute_script( 35 | "window.scrollTo(0, document.body.scrollHeight);") 36 | # 等待数据加载 37 | time.sleep(1) 38 | # 如果当前页面和上一个页面的 html 内容不同,则表明滑动到底部了 39 | if initial_pagesource == driver.page_source: 40 | break 41 | initial_pagesource = driver.page_source 42 | 43 | # 使用 BeautifulSoup 解析 html 内容 44 | soup = BeautifulSoup(initial_pagesource) 45 | # 获取搜索结果的每一个项 46 | result = soup.find_all("div", class_=["search_table_header", ]) 47 | result_list = [] 48 | for ticket_info in result: 49 | try: 50 | # 航空公司名、出发时间、到达时间 51 | company_name, start_time, arrival_time = [ 52 | x.text for x in ticket_info.find_all('strong')] 53 | # 出发机场、到达机场 54 | start_airport, arrival_airport = [ 55 | x.text for x in ticket_info.find_all("div", class_=["airport", ])] 56 | tmp = [x.text for x in ticket_info.find_all( 57 | "span", class_=["direction_black_border", ])] 58 | # 飞机类型,准点率(可能没有) 59 | if len(tmp) == 2: 60 | airpane_type, ontime_rate = tmp 61 | ontime_rate = float(''.join(filter(str.isdigit, ontime_rate)))/100 62 | else: 63 | airpane_type = tmp[0] 64 | ontime_rate = 0 65 | # 航班编号 66 | airpane_number = [x.text for x in ticket_info.find_all("span")][2] 67 | # 价格(经济舱) 68 | price = int([''.join(list(filter(str.isdigit, x.text))) 69 | for x in ticket_info.find_all("span", class_=["base_price02", ])][0]) 70 | result_list.append([company_name, start_time, arrival_time, start_airport, 71 | arrival_airport, airpane_type, ontime_rate, airpane_number, price]) 72 | 73 | except Exception as E: 74 | print(E) 75 | 76 | # 按机票价格排序后返回 77 | return sorted(result_list, key=lambda x: x[-1]) 78 | 79 | if __name__ == "__main__": 80 | # driver = webdriver.PhantomJS(executable_path="./chromedriver", service_args=['--load-images=no']) 81 | options = Options() 82 | # options = webdriver.ChromeOptions() 83 | # options.add_argument("--headless") # Runs Chrome in headless mode. 84 | options.add_argument('--no-sandbox') # # Bypass OS security model 85 | options.add_argument('start-maximized') 86 | options.add_argument('disable-infobars') 87 | options.add_argument("--disable-extensions") 88 | driver = webdriver.Chrome(options=options, executable_path='./chromedriver') 89 | # driver = webdriver.Chrome("./chromedriver") 90 | result_list = get_ticket_info('CTU', 'SHA', '2018-10-30', driver) 91 | print(result_list) -------------------------------------------------------------------------------- /Assignments/README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | 实验楼《楼+ 数据分析与挖掘实战》优秀项目挑战报告|课程报名 4 |
5 | 6 |
7 | 8 | 如果 Github 加载缓慢,可以点击下方链接快速浏览。👇 9 | 10 | ### 第 1 期课程 11 | 12 | - 报告题目:[中国保险业过去五年基础数据分析](https://nbviewer.jupyter.org/github/shiyanlou/louplus-dm/blob/master/Assignments/%F0%9F%8F%85%EF%B8%8Fdm01-stenphen-%E4%B8%AD%E5%9B%BD%E4%BF%9D%E9%99%A9%E4%B8%9A%E8%BF%87%E5%8E%BB%E4%BA%94%E5%B9%B4%E5%9F%BA%E7%A1%80%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90.ipynb)|学员昵称:stenphen 🌟 13 | - 报告题目:[上海历史天气数据分析预测](https://nbviewer.jupyter.org/github/shiyanlou/louplus-dm/blob/master/Assignments/%F0%9F%8F%85%EF%B8%8Fdm01-stenphen-%E4%B8%AD%E5%9B%BD%E4%BF%9D%E9%99%A9%E4%B8%9A%E8%BF%87%E5%8E%BB%E4%BA%94%E5%B9%B4%E5%9F%BA%E7%A1%80%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90.ipynb)|学员昵称:BellaG 14 | - 报告题目:[双色球历史数据统计预测](https://nbviewer.jupyter.org/github/shiyanlou/louplus-dm/blob/master/Assignments/%F0%9F%A5%89dm01-hcccom-%E5%8F%8C%E8%89%B2%E7%90%83%E5%8E%86%E5%8F%B2%E6%95%B0%E6%8D%AE%E7%BB%9F%E8%AE%A1%E9%A2%84%E6%B5%8B.ipynb)|学员昵称:hcccom 15 | 16 | ### 第 2 期课程 17 | 18 | - 报告题目:[杭州互联网寒冬背景下的数据分析岗现状分析](https://nbviewer.jupyter.org/github/shiyanlou/louplus-dm/blob/master/Assignments/%F0%9F%8F%85%EF%B8%8Fdm02-%E7%B1%B3%E7%AB%B9314159-%E6%9D%AD%E5%B7%9E%E4%BA%92%E8%81%94%E7%BD%91%E5%AF%92%E5%86%AC%E8%83%8C%E6%99%AF%E4%B8%8B%E7%9A%84%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E5%B2%97%E7%8E%B0%E7%8A%B6%E5%88%86%E6%9E%90.ipynb)|学员昵称:米竹314159 🌟 19 | - 报告题目:[医学专业论坛的数据爬取和分析](https://nbviewer.jupyter.org/github/shiyanlou/louplus-dm/blob/master/Assignments/%F0%9F%A5%88dm02-linnecn-%E5%8C%BB%E5%AD%A6%E4%B8%93%E4%B8%9A%E8%AE%BA%E5%9D%9B%E7%9A%84%E6%95%B0%E6%8D%AE%E7%88%AC%E5%8F%96%E5%92%8C%E5%88%86%E6%9E%90.ipynb)|学员昵称:linnecn 20 | 21 | ### 第 3 期课程 22 | 23 | - 虚位以待 24 | 25 | ### 第 4 期课程 26 | 27 | - 报告题目:[链家成都市区挂牌二手房分析](https://nbviewer.jupyter.org/github/shiyanlou/louplus-dm/blob/master/Assignments/%F0%9F%8F%85%EF%B8%8Fdm04-Luo2019-%E9%93%BE%E5%AE%B6%E6%88%90%E9%83%BD%E5%B8%82%E5%8C%BA%E6%8C%82%E7%89%8C%E4%BA%8C%E6%89%8B%E6%88%BF%E5%88%86%E6%9E%90.ipynb)|学员昵称:Luo2019 🌟 28 | - 报告题目:[B 站番剧数据简单分析](https://nbviewer.jupyter.org/github/shiyanlou/louplus-dm/blob/master/Assignments/%F0%9F%A5%88dm04-Yueyec-B-%E7%AB%99%E7%95%AA%E5%89%A7%E6%95%B0%E6%8D%AE%E7%AE%80%E5%8D%95%E5%88%86%E6%9E%90.ipynb)|学员昵称:Yueyec 29 | 30 | ### 第 5 期课程 31 | 32 | - 报告题目:[京东手机销售数据分析](https://www.kaggle.com/ted0001/dm05-998494)|学员昵称:[Ted_Wei](https://www.lanqiao.cn/users/998494/) 🌟 33 | - 报告题目:[通信基站室内分布系统外引小区识别](https://www.kaggle.com/cym1085893/dm05-1085893)|学员昵称:[yiming_chen](https://www.lanqiao.cn/users/1085893/) 34 | 35 | ### 第 6 期课程 36 | 37 | - 报告题目:[大连地区酒店数据分析](https://www.kaggle.com/louplus/dm06-937174)|学员昵称:[Miss_candy](https://www.lanqiao.cn/users/937174/) 🌟 38 | 39 | ### 第 7 期课程 40 | 41 | - 报告题目:[微博搜索“双十一”数据分析](https://www.kaggle.com/lanjie/dm07-1127847)|学员昵称:[灵汐](https://www.lanqiao.cn/users/1127847/) 42 | 43 | ### 第 8 期课程 44 | 45 | - 报告题目:[B站up主“老番茄”基本数据采集分析](https://www.kaggle.com/truwbin/dm08-877339-b-up)|学员昵称:[今天小古不出门](https://www.lanqiao.cn/users/877339/) 🌟 46 | - 报告题目:[下厨房家常菜菜谱分析及新菜谱预测评分](https://www.kaggle.com/fors3c/dm08-ns3c)|学员昵称:ns3c 47 | 48 | ### 第 9 期课程 49 | 50 | - 报告题目:[世界银行国际旅游业指标分析](https://www.kaggle.com/furongrong/dm09-535211)|学员昵称:[RR25](https://www.lanqiao.cn/users/535211/) 🌟 51 | - 报告题目:[猪肉价格数据分析](https://www.kaggle.com/suxiaomo/dm09-1180757)|学员昵称:[苏小墨](https://www.lanqiao.cn/users/1180757/) 52 | - 报告题目:[汽车之家数据分析](https://www.kaggle.com/mengchenshang/dm09-1176812)|学员昵称:[凹润纸](https://www.lanqiao.cn/users/1176812/) 53 | 54 | ### 第 10 期课程 55 | 56 | - 虚位以待 57 | 58 | ### 第 11 期课程 59 | 60 | - 报告题目:[科比职业生涯回顾与模型预测](https://www.kaggle.com/yemujianglin/dm11-1276351)|学员昵称:[夜幕降临_](https://www.lanqiao.cn/users/1276351/) 🌟 61 | 62 | ### 第 12 期课程 63 | 64 | - 虚位以待 65 |
66 | 67 | ### 第 13 期课程 68 | 69 | - 报告题目:[基于 Python 语言的加拿大联邦大选数据分析](https://www.kaggle.com/czz1403/dm13-1204880-python)|学员昵称:[TXZXTLD](https://www.lanqiao.cn/users/1204880/) 🌟 70 | - 报告题目:[新冠疫情社会影响数据分析](https://www.kaggle.com/vincentbao/dm13-812273)|学员昵称:[vincentbao](https://www.lanqiao.cn/users/812273/) 🌟 已经制作成课程:https://www.lanqiao.cn/courses/2791 71 | 72 | 73 | ``` 74 | - 原作者可以提 PR 更新自己的报告内容。 75 | - 实验报告版权归属原学员且授权实验楼独家使用,请勿用于商业用途。 76 | ``` 77 | -------------------------------------------------------------------------------- /Assignments/🥉dm01-hcccom-双色球历史数据统计预测.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 双色球历史数据统计预测" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "---" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "- 报告题目:双色球历史数据统计预测\n", 22 | "- 学员昵称:hcccom\n", 23 | "- 课程期数:第一期" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "© 本文著作权归作者所有,并授权实验楼独家使用,未经实验楼许可,不得转载使用。" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "---" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "### 获取数据" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "import random\n", 54 | "import numpy as np\n", 55 | "import requests\n", 56 | "import csv\n", 57 | "from bs4 import BeautifulSoup\n", 58 | "headers = {\n", 59 | " 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'}\n", 60 | "res = requests.get(\n", 61 | " 'https://datachart.500.com/ssq/history/newinc/history.php?start=03001&end=18147', headers=headers) # 从03年第一期开始\n", 62 | "res.encoding = 'uft-8'\n", 63 | "soup = BeautifulSoup(res.text, 'lxml')\n", 64 | "data = soup.find_all(attrs={'class': 't_tr1'})\n", 65 | "csvFile = open(\"./ssq004.csv\", 'wt', newline='', encoding='utf-8')" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": null, 71 | "metadata": {}, 72 | "outputs": [], 73 | "source": [ 74 | "def gens(x): # 模拟\n", 75 | " random.seed(x)\n", 76 | " a = np.arange(1, 34, 1).tolist()\n", 77 | " red = sorted(random.sample(a, 6))\n", 78 | " b = np.arange(1, 17, 1).tolist()\n", 79 | " blue = random.sample(b, 1)\n", 80 | " red.extend(blue)\n", 81 | " return red" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 8, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "with open(r\"ssq004.csv\", 'a', newline='') as f:\n", 91 | " writer = csv.writer(f)\n", 92 | " writer.writerow([\"period\", \"real\", \"date\", \"vis\", 'r1',\n", 93 | " 'r2', 'r3', 'r4', 'r5', 'r6', 'b1']) # 先写入列名\n", 94 | " for i in range(0, len(data)):\n", 95 | " period = data[i].find_all('td')[0].text\n", 96 | " real = [int(data[i].find_all('td')[1].text), int(data[i].find_all('td')[2].text), int(data[i].find_all('td')[3].text), int(data[i].find_all(\n", 97 | " 'td')[4].text), int(data[i].find_all('td')[5].text), int(data[i].find_all('td')[6].text), int(data[i].find_all('td')[7].text)]\n", 98 | " date = data[i].find_all('td')[15].text\n", 99 | " vis = gens(date)\n", 100 | " r1 = int(data[i].find_all('td')[1].text)\n", 101 | " r2 = int(data[i].find_all('td')[2].text)\n", 102 | " r3 = int(data[i].find_all('td')[3].text)\n", 103 | " r4 = int(data[i].find_all('td')[4].text)\n", 104 | " r5 = int(data[i].find_all('td')[5].text)\n", 105 | " r6 = int(data[i].find_all('td')[6].text)\n", 106 | " b1 = int(data[i].find_all('td')[7].text)\n", 107 | "\n", 108 | " writer.writerows(\n", 109 | " [[period, real, date, vis, r1, r2, r3, r4, r5, r6, b1]])\n", 110 | "csvFile.close()" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "### 数据处理" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": 9, 123 | "metadata": {}, 124 | "outputs": [ 125 | { 126 | "data": { 127 | "text/plain": [ 128 | "[3, 6, 8, 23, 25, 33, 4]" 129 | ] 130 | }, 131 | "execution_count": 9, 132 | "metadata": {}, 133 | "output_type": "execute_result" 134 | } 135 | ], 136 | "source": [ 137 | "import pandas as pd\n", 138 | "import matplotlib.pyplot as plt\n", 139 | "df = pd.read_csv('ssq004.csv', encoding='gbk')\n", 140 | "df.set_index(\"date\", inplace=True)\n", 141 | "df.index = pd.DatetimeIndex(df.index)\n", 142 | "df.sort_index(ascending=True, inplace=True)\n", 143 | "\n", 144 | "\n", 145 | "def get_real(i):\n", 146 | " a = df.real[i]\n", 147 | " lista = a.strip('[]').split(',')\n", 148 | " map(int, lista)\n", 149 | " list_real = [int(x) for x in lista]\n", 150 | " return list_real\n", 151 | "\n", 152 | "\n", 153 | "def get_vis(i): # 产生和时间相关的随机双色球\n", 154 | " b = df.vis[i]\n", 155 | " listb = b.strip('[]').split(',')\n", 156 | " map(int, listb)\n", 157 | " list_vis = [int(x) for x in listb]\n", 158 | " return list_vis\n", 159 | "\n", 160 | "\n", 161 | "get_vis(1)" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "metadata": {}, 168 | "outputs": [], 169 | "source": [ 170 | "# 计算每个球出现的频率" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 10, 176 | "metadata": { 177 | "scrolled": true 178 | }, 179 | "outputs": [], 180 | "source": [ 181 | "df1 = df.drop(columns=['period', 'real', 'vis'])\n", 182 | "df2 = df1.drop(columns=['b1'])\n", 183 | "df3 = df1[['b1']]\n", 184 | "dup = df1[df1.duplicated()].count()\n", 185 | "rd1 = df2.stack().value_counts()\n", 186 | "bd1 = df3['b1'].value_counts()" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 11, 192 | "metadata": { 193 | "scrolled": false 194 | }, 195 | "outputs": [ 196 | { 197 | "data": { 198 | "image/png": "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\n", 199 | "text/plain": [ 200 | "
" 201 | ] 202 | }, 203 | "metadata": { 204 | "needs_background": "light" 205 | }, 206 | "output_type": "display_data" 207 | }, 208 | { 209 | "data": { 210 | "image/png": "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\n", 211 | "text/plain": [ 212 | "
" 213 | ] 214 | }, 215 | "metadata": { 216 | "needs_background": "light" 217 | }, 218 | "output_type": "display_data" 219 | } 220 | ], 221 | "source": [ 222 | "import matplotlib.pyplot as plt\n", 223 | "from pylab import *\n", 224 | "plt.figure(111)\n", 225 | "rd1.plot(kind='bar', align='center')\n", 226 | "plt.xlabel(\"red\")\n", 227 | "plt.ylabel(\"Times\")\n", 228 | "plt.show()\n", 229 | "plt.figure(112)\n", 230 | "bd1.plot(kind='bar')\n", 231 | "plt.xlabel(\"blue\")\n", 232 | "plt.ylabel(\"Times\")\n", 233 | "plt.show()" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "metadata": {}, 239 | "source": [ 240 | "### 取一组\n", 241 | " " 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 14, 247 | "metadata": {}, 248 | "outputs": [ 249 | { 250 | "data": { 251 | "text/html": [ 252 | "
\n", 253 | "\n", 266 | "\n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | " \n", 276 | " \n", 277 | " \n", 278 | " \n", 279 | " \n", 280 | " \n", 281 | " \n", 282 | " \n", 283 | " \n", 284 | " \n", 285 | " \n", 286 | " \n", 287 | " \n", 288 | " \n", 289 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | " \n", 324 | " \n", 325 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | " \n", 362 | "
periodrealvisr1r2r3r4r5r6b1
date
2018-12-0418142[5, 8, 10, 11, 27, 28, 11][11, 13, 16, 24, 29, 31, 8]581011272811
2018-12-0618143[4, 6, 15, 28, 32, 33, 14][10, 14, 15, 16, 24, 33, 14]461528323314
2018-12-0918144[8, 13, 17, 18, 20, 27, 13][3, 7, 13, 17, 19, 30, 13]8131718202713
2018-12-1118145[3, 9, 13, 22, 23, 25, 6][3, 6, 10, 12, 19, 25, 12]39132223256
2018-12-1318146[2, 10, 11, 17, 18, 29, 16][6, 10, 21, 24, 26, 32, 3]2101117182916
\n", 363 | "
" 364 | ], 365 | "text/plain": [ 366 | " period real vis \\\n", 367 | "date \n", 368 | "2018-12-04 18142 [5, 8, 10, 11, 27, 28, 11] [11, 13, 16, 24, 29, 31, 8] \n", 369 | "2018-12-06 18143 [4, 6, 15, 28, 32, 33, 14] [10, 14, 15, 16, 24, 33, 14] \n", 370 | "2018-12-09 18144 [8, 13, 17, 18, 20, 27, 13] [3, 7, 13, 17, 19, 30, 13] \n", 371 | "2018-12-11 18145 [3, 9, 13, 22, 23, 25, 6] [3, 6, 10, 12, 19, 25, 12] \n", 372 | "2018-12-13 18146 [2, 10, 11, 17, 18, 29, 16] [6, 10, 21, 24, 26, 32, 3] \n", 373 | "\n", 374 | " r1 r2 r3 r4 r5 r6 b1 \n", 375 | "date \n", 376 | "2018-12-04 5 8 10 11 27 28 11 \n", 377 | "2018-12-06 4 6 15 28 32 33 14 \n", 378 | "2018-12-09 8 13 17 18 20 27 13 \n", 379 | "2018-12-11 3 9 13 22 23 25 6 \n", 380 | "2018-12-13 2 10 11 17 18 29 16 " 381 | ] 382 | }, 383 | "execution_count": 14, 384 | "metadata": {}, 385 | "output_type": "execute_result" 386 | } 387 | ], 388 | "source": [ 389 | "df.tail(5)" 390 | ] 391 | }, 392 | { 393 | "cell_type": "code", 394 | "execution_count": 15, 395 | "metadata": {}, 396 | "outputs": [ 397 | { 398 | "data": { 399 | "text/plain": [ 400 | "[]" 401 | ] 402 | }, 403 | "execution_count": 15, 404 | "metadata": {}, 405 | "output_type": "execute_result" 406 | }, 407 | { 408 | "data": { 409 | "image/png": "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\n", 410 | "text/plain": [ 411 | "
" 412 | ] 413 | }, 414 | "metadata": { 415 | "needs_background": "light" 416 | }, 417 | "output_type": "display_data" 418 | } 419 | ], 420 | "source": [ 421 | "x = [1, 2, 3, 4, 5, 6, 7]\n", 422 | "y1 = get_real(-1)\n", 423 | "y2 = get_vis(-1)\n", 424 | "fig, ax = plt.subplots(figsize=(15, 5))\n", 425 | "ax.plot(x, y1, 'ch-', markersize=10)\n", 426 | "ax.plot(x, y2, 'ys-', markersize=10)" 427 | ] 428 | }, 429 | { 430 | "cell_type": "code", 431 | "execution_count": 167, 432 | "metadata": {}, 433 | "outputs": [ 434 | { 435 | "data": { 436 | "image/png": "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\n", 437 | "text/plain": [ 438 | "
" 439 | ] 440 | }, 441 | "metadata": { 442 | "needs_background": "light" 443 | }, 444 | "output_type": "display_data" 445 | }, 446 | { 447 | "data": { 448 | "text/plain": [ 449 | "array([0.95333787, 3.40088556])" 450 | ] 451 | }, 452 | "execution_count": 167, 453 | "metadata": {}, 454 | "output_type": "execute_result" 455 | } 456 | ], 457 | "source": [ 458 | "x_data = np.array(y1)\n", 459 | "\n", 460 | "y_data = np.array(y2)\n", 461 | "\n", 462 | "poly = np.polyfit(x_data, y_data, deg=1)\n", 463 | "\n", 464 | "plt.plot(x_data, y_data, 'o')\n", 465 | "\n", 466 | "plt.plot(x_data, np.polyval(poly, x_data))\n", 467 | "\n", 468 | "plt.show()\n", 469 | "poly" 470 | ] 471 | }, 472 | { 473 | "cell_type": "code", 474 | "execution_count": 7, 475 | "metadata": {}, 476 | "outputs": [ 477 | { 478 | "data": { 479 | "image/png": "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\n", 480 | "text/plain": [ 481 | "
" 482 | ] 483 | }, 484 | "metadata": { 485 | "needs_background": "light" 486 | }, 487 | "output_type": "display_data" 488 | }, 489 | { 490 | "data": { 491 | "text/plain": [ 492 | "array([-2.44332198e-03, 1.76012475e-01, -4.58949704e+00, 5.31642494e+01,\n", 493 | " -2.57338653e+02, 3.41987935e+02])" 494 | ] 495 | }, 496 | "execution_count": 7, 497 | "metadata": {}, 498 | "output_type": "execute_result" 499 | } 500 | ], 501 | "source": [ 502 | "x_data = np.array(y1)\n", 503 | "\n", 504 | "y_data = np.array(y2)\n", 505 | "\n", 506 | "poly = np.polyfit(x_data, y_data, deg=5)\n", 507 | "\n", 508 | "plt.plot(x_data, y_data, 'o')\n", 509 | "\n", 510 | "plt.plot(x_data, np.polyval(poly, x_data))\n", 511 | "\n", 512 | "plt.show()\n", 513 | "poly" 514 | ] 515 | }, 516 | { 517 | "cell_type": "markdown", 518 | "metadata": {}, 519 | "source": [ 520 | "各种分析过后,仍无法做出预测。。。。。" 521 | ] 522 | }, 523 | { 524 | "cell_type": "markdown", 525 | "metadata": {}, 526 | "source": [ 527 | "结论:双色球是无法预测的" 528 | ] 529 | }, 530 | { 531 | "cell_type": "markdown", 532 | "metadata": {}, 533 | "source": [ 534 | "---" 535 | ] 536 | }, 537 | { 538 | "cell_type": "markdown", 539 | "metadata": {}, 540 | "source": [ 541 | "#### 评阅意见反馈" 542 | ] 543 | }, 544 | { 545 | "cell_type": "markdown", 546 | "metadata": {}, 547 | "source": [ 548 | "
\n", 549 | "hcccom 提交的《双色球历史数据统计预测》项目挑战报告初步达到课程挑战要求,但仍然有很多地方值得完善。\n", 550 | "

\n", 551 | "数据采集部分内容不错,能采集完整的双色球投注数据。但缺乏必要的解释和代码注释。数据分析和处理阶段仅对各号球的出现频次做了统计,选择的柱形图虽然合理但内容较为单薄。这里,建议可以对连续 2 球或者多球的出现频次统计分析。或者分析不同位置各号球的出现频次,或许从统计学角度更有意义。\n", 552 | "

\n", 553 | "「取一组」小节之后没有看明白分析的用意,或许是想预测各号球如何出现?不过这样肯定无法完成的。回归分析显然不能用于这里的预测过程。\n", 554 | "

\n", 555 | "总之,该挑战报告有 2 点值得改善的地方:\n", 556 | "\n", 557 | "- 补充陈述内容,让阅读者知道每一步的大致操作用意。整个分析报告几乎没有解释性语句,非常不赞同这样做。数据分析的过程很重要,实际上阐述结论和讲好一个故事更加重要。\n", 558 | "\n", 559 | "- 分析思路没有理清,显然双色球出现是随机事件,这是无法通过回归分析完成的。所以,挑战的选题从一开始就不太理想。实际上,就算是真实的数据分析任务,也不建议去做彩票预测,因为就算从概率上得到了一些高频次组合方式,但没有明确的指导意义。\n", 560 | "\n", 561 | "代码方面,注意不用写重复冗余代码(类似 plt.show() 在同单元格多次出现)。后期在书写代码时注意按照 PEP8 格式化即可。VS Code 等 IDE 带有相关格式化插件,Jupyter Notebook 也可以通过安装 jupyter_contrib_nbextensions 拓展开启相关插件自动完成代码格式化。\n", 562 | "

\n", 563 | "总之,通过该报告可以判定学员初步达到我们课程预设的培养目标,但仍需要继续学习和加深对数据分析各环节的思考。希望 hcccom 后续再通过书籍等拓展更多相关的数据分析和挖掘知识,并结合自己的兴趣及专业特长在数据分析的道路上越走越好。\n", 564 | "
\n", 565 | "\n", 566 | "


\n", 567 | "
楼+ 数据分析和挖掘课程组
\n", 568 | "
2018 年 12 月 17 日
" 569 | ] 570 | }, 571 | { 572 | "cell_type": "markdown", 573 | "metadata": {}, 574 | "source": [ 575 | "---" 576 | ] 577 | } 578 | ], 579 | "metadata": { 580 | "kernelspec": { 581 | "display_name": "Python 3", 582 | "language": "python", 583 | "name": "python3" 584 | }, 585 | "language_info": { 586 | "codemirror_mode": { 587 | "name": "ipython", 588 | "version": 3 589 | }, 590 | "file_extension": ".py", 591 | "mimetype": "text/x-python", 592 | "name": "python", 593 | "nbconvert_exporter": "python", 594 | "pygments_lexer": "ipython3", 595 | "version": "3.7.1" 596 | } 597 | }, 598 | "nbformat": 4, 599 | "nbformat_minor": 2 600 | } 601 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 实验楼在线教育 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Mindmaps/README.md: -------------------------------------------------------------------------------- 1 | - [点击下载全部思维导图](https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/shiyanlou/louplus-dm/tree/master/Mindmaps) 2 | -------------------------------------------------------------------------------- /Mindmaps/louplus-dm-week1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyanlou/louplus-dm/52764983b7080c3ca760e38c38c9a71cf0c2ed3e/Mindmaps/louplus-dm-week1.png -------------------------------------------------------------------------------- /Mindmaps/louplus-dm-week2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyanlou/louplus-dm/52764983b7080c3ca760e38c38c9a71cf0c2ed3e/Mindmaps/louplus-dm-week2.png -------------------------------------------------------------------------------- /Mindmaps/louplus-dm-week3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyanlou/louplus-dm/52764983b7080c3ca760e38c38c9a71cf0c2ed3e/Mindmaps/louplus-dm-week3.png -------------------------------------------------------------------------------- /Mindmaps/louplus-dm-week4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyanlou/louplus-dm/52764983b7080c3ca760e38c38c9a71cf0c2ed3e/Mindmaps/louplus-dm-week4.png -------------------------------------------------------------------------------- /Mindmaps/louplus-dm-week5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiyanlou/louplus-dm/52764983b7080c3ca760e38c38c9a71cf0c2ed3e/Mindmaps/louplus-dm-week5.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | 蓝桥云课《楼+ 数据分析与挖掘实战》课程仓库|课程报名 4 |
5 | 6 |
7 | 8 | 主分支下方包含最新课程的参考答案,历史开班课程的参考答案移步相应分支查看。 9 | 10 | ### 其他班级 11 | 12 | - [第 12-13 期挑战参考答案](https://github.com/shiyanlou/louplus-dm/tree/v3/Answers) 13 | - [第 07-11 期挑战参考答案](https://github.com/shiyanlou/louplus-dm/tree/v2/Answers) 14 | - [第 01-06 期挑战参考答案](https://github.com/shiyanlou/louplus-dm/tree/master/Answers) 15 | 16 | ### 优秀报告 17 | 18 | - [优秀项目挑战比赛报告](https://github.com/shiyanlou/louplus-dm/tree/master/Assignments) 19 | --------------------------------------------------------------------------------