返回介绍

附录 2 单星项目的解决方案

发布于 2024-01-28 22:01:15 字数 11250 浏览 0 评论 0 收藏 0

此附录挑选了一些(单星)项目,给出了参考的解决方案。这些解决方案使用了最具Python风格的方式。如果你的解决方案与给出的不一致,也没有必要纠结!编程问题的解决方案本来就不止一种,这就如同有多种描写爱情和死亡的方法一样。

Hello, World!

编写一个在Python命令行输出“Hello, World!”的程序(第1章的问题)。

solution-hello.py

# 尊重传统
print("Hello, World!")

词频计数器

编写一个程序,用于下载用户请求的网页,并给出网页中使用频率最高的十个词,所有词不区分大小写。出于练习的目的,可以简单地假设一个词由正则表达式r"\w+"确定(第2章的问题)。

solution-counter.py

import urllib.request, re
from collections import Counter

# 建立与用户以及与网络的会话
url = input("Enter the URL: ")
try:
    page = urllib.request.urlopen(url)
except:
    print("Cannot open %s" % url)
    quit()

# 读取页面,并完成部分规范化操作
doc = page.read().decode().lower()

# 将文本切分为词语
words = re.findall(r"\w+", doc)

# 构建计数器并给出结果
print(Counter(words).most_common(10))

失效链接检测器

编写一个程序,基于一个给定网页的URL,报出页面中失效链接的名称和地址。出于练习的目的,约定当使用urllib.request.urlopen()打开链接失败时,则认为链接失效(第3章的问题)。

solution-broken_link.py

import urllib.request, urllib.parse
import bs4 as BeautifulSoup

# 建立与用户以及与网络的会话
base = input("Enter the URL: ")
try:
    page = urllib.request.urlopen(base)
except:
    print("Cannot open %s" % base)
    quit()

# 准备soup
soup = BeautifulSoup.BeautifulSoup(page)

# 提取链接,并用(名称,网址)的元组表示
links = [(link.string, link["href"])
         for link in soup.find_all("a")
         if link.has_attr("href")]

# 尝试打开每个链接
broken = False
for name, url in links:
    # 将base和链接目标组合在一起
    dest = urllib.parse.urljoin(base, url)
    try:
        page = urllib.request.urlopen(dest)
        page.close()
    except:
        print("Link \"%s\" to \"%s\" is probably broken." % (name, dest))
        broken = True

# 显示好消息!
if not broken:
    print("Page %s does not seem to have broken links." % base)

MySQL文件索引器

编写一个Python程序,对于给定文件中的每个单词,记录如下信息到MySQL数据库中:单词本身(不是词干!)、单词在文件中的序数(从1开始),以及单词的词性标记。使用NLTK WordPunct-Tokenizer(参考第16单元第2小节)来识别单词。假设这些单词比较短,数据类型可以使用MySQL的TINYTEXT。设计数据库模式,创建所有必需的表,并在正式开始编写Python代码之前,通过命令行来试用一下设计出来的表(第4章的问题)。

该解决方案由两个文件组成:一个是设置表的MySQL脚本,另一个是执行索引的Python程序。

solution-mysql_indexer.sql

CREATE TABLE IF NOT EXISTS indexer(id INT PRIMARY KEY AUTO_INCREMENT,
                                   ts TIMESTAMP,
                                   word TINYTEXT,
                                   position INT,
                                   pos VARCHAR(8));

solution-mysql-indexer.py

import nltk, pymysql

infilename = input("Enter the name of the file to index: ")

# 结合你的MySQL服务器的设置改变本行
conn = pymysql.connect(user="dsuser", passwd="badpassw0rd", db="dsbd")
cur = conn.cursor()

QUERY = "INSERT INTO indexer (word,position,pos) VALUES "
wpt = nltk.WordPunctTokenizer()

offset = 1
with open(infilename) as infile:
    # 使用增量方式处理文本,每次处理一行
    # 不论如何,一个词不可能跨行分布
    for text in infile:
        # 分词并加入POS标签
        pieces = enumerate(nltk.pos_tag(wpt.tokenize(text)))

        # 创建一个查询命令;别忘了要避开待查询的词!
        words = ["(\"%s\",%d,\"%s\")" % (conn.escape_string(w),
                                         i + offset,
                                         conn.escape_string(pos))
                 for (i, (w, pos)) in pieces]

        # 执行查询命令
        if words:
            cur.execute(QUERY + ','.join(words))

            # 移动词的位置指针
            offset += len(words)

# 提交更改
conn.commit()
conn.close()

数组微分器

(函数的)部分和近似等价于(函数的)积分。事实上,微积分理论就把积分定义为无穷小元素的无限求和。(函数的)部分差arri+1-arri近似等价于(函数的)导数。numpy没有提供用于计算数组部分差的工具。请编写一个程序,对于一个给定的数组arr,计算数组项的部分差。在本练习中假设数组为数值数组(第5章的问题)。

solution-difference.py

import numpy as np

# 用于测试的合成数据
array = np.random.binomial(5, 0.5, size=100)

# 计算数组部分差:切片&广播!
diff = array[1:] - array[:-1]

猞猁的捕获量

写一个程序,使用每年加拿大猞猁的捕获量1给出每十年的猞猁捕获总量,并将结果按逆序排列(最“有效益的”十年排在前面)。如果cache目录中不存在数据文件,则程序自动将数据下载到cache目录中。如果cache目录不存在,则程序将自动创建该目录。程序将计算结果保存到doc目录下的CSV文件中。如果doc目录不存在,则程序将自动创建该目录(第6章的问题)。

solution-lynx.py

import os, pandas as pd
import urllib.request

# 一些“常量”
SRC_HOST = "https://vincentarelbundock.github.io"
FILE = "/lynx.csv"
SRC_NAME = SRC_HOST + "/Rdatasets/csv/datasets" + FILE
CACHE = "cache"
DOC = "doc"

# 在需要时创建目录
if not os.path.isdir(CACHE):
    os.mkdir(CACHE)
if not os.path.isdir(DOC):
    os.mkdir(DOC)

# 检查文件是否缓存;如未缓存就进行缓存处理
if not os.path.isfile(CACHE + FILE):
    try:
        src = urllib.request.urlopen(SRC_NAME)
        lynx = pd.read_csv(src)
    except:
        print("Cannot access %f." % SRC_NAME)
        quit()
    # 创建数据frame
    lynx.to_csv(CACHE + FILE)
else:
    lynx = pd.read_csv(CACHE + FILE)

# 加入“decade”列
lynx["decade"] = (lynx['time'] / 10).round() * 10

# 求和并排序
by_decade = lynx.groupby("decade").sum()
by_decade = by_decade.sort_values(by="lynx", ascending=False)

# 保存结果
by_decade["lynx"].to_csv(DOC + FILE)

中心性的相关问题

从斯坦福大网络数据集2中下载Epinions.com网站用户的社交网络图,并提取出规模排名第十的社区。编写一个程序,计算并显示第7章中提到的所有网络中心性度量之间的两两相关性;加入集聚系数可以使问题变得更加有趣(第7章的问题)。建议你使用pandas的frame来存储所有中心性。你可能需要阅读第47单元第2小节来了解如何使用pandas计算相关性。

是否存在强相关的一对中心性?

solution-centrality.py

   import networkx as nx, community
   import pandas as pd

   # 导入network模块
   G = nx.read_adjlist(open("soc-Epinions1.txt", "rb"))

   # 提取社区结构并用series保存
   partition = pd.Series(community.best_partition(G))

   # 找出10个最大社区的索引
   top10 = partition.value_counts().index[9]

   # 提取10大社区
   # 注意节点的标签是字符串!
   subgraph = partition[partition == top10].index.values.astype('str')
   F = G.subgraph(subgraph)

   # 计算网络的度量
   df = pd.DataFrame()
   df["degree"] = pd.Series(nx.degree_centrality(F))

   df["closeness"] = pd.Series(nx.closeness_centrality(F))
   df["betweenness"] = pd.Series(nx.betweenness_centrality(F))
   df["eigenvector"] = pd.Series(nx.eigenvector_centrality(F))
   df["clustering"] = pd.Series(nx.clustering(F))

   # 计算相关性
   print(df.corr())

➾               degree  closeness  betweenness  eigenvector  clusteringdegree      1.000000   0.247377     0.871812     0.738836    0.100259closeness   0.247377   1.000000     0.169449     0.547228    0.024052betweenness 0.871812   0.169449     1.000000     0.527290   -0.015759eigenvector 0.738836   0.547228     0.527290     1.000000    0.143070clustering  0.100259   0.024052    -0.015759     0.143070    1.000000

度中心性与中介中间性以及特征矢量中心性呈强的线性相关关系。

美国派

编写一个程序,将美国的所有州按首字母分组,并用一个饼图显示分组结果或保存为PDF文件。为了完成该项目,你需要用到州的名称或其缩写的列表,这个列表可以从命名网站获取3(第8章的问题)。

solution-states-pie.py

import pandas as pd
import matplotlib, matplotlib.pyplot as plt

def initial(word):
    return word[0]

# 读取州名(可以使用任何你喜欢的数据源!)
states = pd.read_csv("states.csv",
                     names=("State", "Standard", "Postal", "Capital"))
# 选取一种优美的绘图样式
matplotlib.style.use("ggplot")

# 绘图
plt.axes(aspect=1)
states.set_index('Postal').groupby(initial).count()['Standard'].plot.pie()
plt.title("States by the First Initial")
plt.ylabel("")

plt.savefig("../images/states-pie.pdf")

得到的饼图如下所示:

21世纪标准普尔500指数

编写一个程序,给出21世纪标准普尔500指数收盘价的一些基本统计量:平均值、标准差、偏斜度以及收盘价和交易量之间的相关性。为了确定得出的相关性是否可靠,可以从Yahoo! Finance4下载历史价格。应注意,21世纪是从2001年1月1日开始的(第9章的问题)。

鉴于新下载的数据不同于本示例中使用的数据,你的答案可能也会不同。

solution-sap.py

   import pandas as pd
   from scipy.stats import pearsonr

   # 读取数据
   sap = pd.read_csv("sapXXI.csv").set_index("Date")

   # 计算并给出统计值的报告
   print("Mean:", sap["Close"].mean())
   print("Standard deviation:", sap["Close"].std())
   print("Skewness:", sap["Close"].skew())
   print("Correlation:\n", sap[["Close", "Volume"]].corr())
   _, p = pearsonr(sap["Close"], sap["Volume"])

   print("p-value:", p)

➾ Mean: 1326.35890044Standard deviation: 332.784759688Skewness: 0.858098114571Correlation:Close   VolumeClose   1.000000 0.103846Volume  0.103846 1.000000p-value: 1.5301705092e-10

结果表明相关性是非常可靠的,但非常微不足道。

MOSN分类

编写一个程序,通过注册用户数量和全球Alexa页面排名⑤,对大量的在线社交网站进行分类。由于站点的排名及其大小差异很大,所以应使用对数尺度来进行聚类和结果呈现(第10章的问题)。

solution-mosn.py

import pandas as pd, numpy as np
import sklearn.cluster, sklearn.preprocessing
import matplotlib, matplotlib.pyplot as plt

# 读取数据
mosn = pd.read_csv('mosn.csv', thousands=',',
                   names=('Name', 'Description', 'Date', 'Registered Users',
                          'Registration', 'Alexa Rank'))
columns = ['Registered Users', 'Alexa Rank']

# 删除有缺失数据和零值的行
good = mosn[np.log(mosn[columns]).notnull().all(axis=1)].copy()

# 聚类
kmeans = sklearn.cluster.KMeans()
kmeans.fit(np.log(good[columns]))
good["Clusters"] = kmeans.labels_

# 找出Facebook
fb = good.set_index('Name').ix['Facebook']['Clusters']

# 选取一种优美的绘图样式
matplotlib.style.use("ggplot")

# 显示结果
ax = good.plot.scatter(columns[0], columns[1], c="Clusters",
                       cmap=plt.cm.Accent, s=100)
plt.title("Massive online social networking sites")
plt.xscale("log")
plt.yscale("log")

# 标记出最出名的站点
def add_abbr(site):
    if site['Clusters'] == fb:
        _ = ax.annotate(site["Name"], site[columns], xytext=(1, 5),
                        textcoords="offset points", size=8,
                        color="darkslategrey")
good.apply(add_abbr, axis=1)

plt.savefig("../images/mosn.png")

1vincentarelbundock.github.io/Rdatasets/csv/datasets/lynx.csv

2snap.stanford.edu/data/soc-Epinions1.html

3www.stateabbreviations.us

4finance.yahoo.com/q/hp?s=^GSP+Historical+Prices

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文