1. 程式人生 > >Python語言程式設計(北京理工大學MOOC)6-8周

Python語言程式設計(北京理工大學MOOC)6-8周

第六週

資料基本處理源程式

def get_num():
    num = []
    numstr = input("請輸入數字,回車鍵結束:")
    while numstr != "":
        num.append(eval(numstr))
        numstr = input("請輸入數字,回車鍵結束:")
    return num
# 求平均值
def mean(num):
    sum = 0.0
    for number in num:
        sum += number
    return sum/len(num)
#求中位數
def median(num):
    sorted(num)
    size = len(num)
    if size%2 ==0:
        med = (num[size//2-1] + num[size//2])/2
    else:
        med = num[size//2]
    return med
#求方差
def dev(num,med):
    sdev = 0.0
    for number in num:
        sdev = sdev + (number - med)**2
    return pow(sdev/(len(num)-1), 0.5)


n = get_num()
m = mean(n)
d = dev(n, m)
print("平均值為{:.2f},中位數為:{},方差為:{:.2f}".format(m, median(n), d))

  1. 集合特點
    -集合用大括號{}表示,元素間用逗號分離
    -集合中每一個元素位移,不存在相同元素
    -集合元素之間無序
  2. 集合的操作方法
    四個操作符
    在這裡插入圖片描述
    再加上兩個關係操作符
    是S<=T或S<T 返回True/False,判斷S和T的子集關係
    是S>=T或S>T 返回True/False,判斷S和T的包含關係
    還有四個增強操作符
    在這裡插入圖片描述
    |操作函式或方法|描述 |
    |–|--|
    | S.add(x) | 如果x不在集合中則將x增加到S |
    | S.discard(x) | 移除S中元素x,如果x不在集合S中,不報錯 |
    | S.remove(x) | 移除S中元素x,如果x不在集合S中,產生KeyError異常|
    | S.clear(x) | 移除S中所有元素 |
    | S.pop(x) | 隨機返回S的一個元素,更新S,若S為空產生KeyError異常 |
    在這裡插入圖片描述

    經典用法:資料去重

    ls = [‘P’, ‘Y’, ‘P’, ‘Y’, 123]
    s = set(ls)
    lt = list(s)
    輸出 [‘P’, ‘Y’, 123]

  3. jieba庫
    jieba是優秀的中文分詞第三方庫,需要額外安裝
    jieba庫提供三種分詞模式,最簡單隻需掌握一個函式
    jieba分詞的原理
    Jieba分詞依靠中文詞庫
    利用一箇中文詞庫,確定漢字之間的關聯概率
    漢字間概率大的組成片語,形成分詞結果
    除了分詞,使用者還可以新增自定義的片語
    最常用的就是:
    jieba.lcut(s) :精確模式,返回一個列表型別的分詞結果
    jieba.lcut(“中國是一個偉大的國家”)
    [‘中國’, ‘是’, ‘一個’, ‘偉大’, ‘的’, ‘國家’]

尋找哈姆雷特高頻詞彙源程式

def getText():
    txt = open("hamlet.txt", "r").read()# 開啟檔案
    txt = txt.lower()# 全部轉化為小寫字母
    for i in '!#$%^&*()_-+=/`~{}[]:;"?<>,.':#去掉全部標點符號用空格代替
        txt = txt.replace(i, " ")
    return txt

hamletTxt = getText()
words = hamletTxt.split()# split 預設用空格將字串分隔並以列表形式返回
counts = {}
for i in words:
    # 計算單詞出現的次數,get函式就是尋找i這個鍵,如果在字典中找到了就返回對應的值,後面那個引數就是default值
    counts[i] = counts.get(i, 0) + 1
# item函式即以列表返回可遍歷的(鍵, 值) 元組陣列([key:value],[key:value],[key:value])
# 再次使用list函式將元祖轉化為列表
items = list(counts.items())
#對列表按照鍵值對的第二個元素進行從大到小的排列
items.sort(key=lambda x:x[1], reverse=True)
for i in range(10):
    word, count = items[i]
    print("{:10}{:5}".format(word, count))#{:10}指定了該域的寬度為10,避免單詞與次數列印效果重複

尋找三國演義人物出場次數源程式

import jieba
txt = open("threekingdoms.txt", "r", encoding="utf-8").read()# 開啟檔案
excludes = {'將軍', '卻說', '荊州', '二人', '不可', '不能', '如此', '商議', '如何', '主公','軍士', '左右', '軍馬', '引兵',\
            '次日', '大喜', '天下', '東吳', '於是', '今日', '不敢', '魏兵', '陛下', '一人', '都督', '人馬', '不知' }
words = jieba.lcut(txt)# 以列表的形式返回
counts = {}
for word in words:
    if len(word) == 1:
        continue
    elif word == "諸葛亮" or word == "孔明曰":
        reword = "孔明"
    elif word == "關公" or word == "雲長":
        reword = "關羽"
    elif word == "玄德" or word == "玄德曰":
        reword = "劉備"
    elif word == "孟德" or word == "丞相":
        reword = "曹操"
    else:
        reword = word
    # 計算單詞出現的次數,get函式就是尋找i這個鍵,如果在字典中找到了就返回對應的值
    counts[reword] = counts.get(reword, 0) + 1
for word in excludes:
   del counts[word]
# item函式即以列表返回可遍歷的(鍵, 值) 元組陣列([key:value],[key:value],[key:value])
# 再次使用list函式將元祖轉化為列表
items = list(counts.items())
#對列表按照鍵值對的第二個元素進行從大到小的排列
items.sort(key=lambda x:x[1], reverse=True)
for i in range(10):
    word, count = items[i]
    print("{:10}{:5}".format(word, count))# {:10}指定了該域的寬度為10
    

明明已經下載jieba庫但是pycha提示沒找到怎麼辦?
file-settings-project-project interpreter,找到右邊的綠色加號,把jieba新增進來就可以了

提示TXT檔案無法讀取怎麼辦?
把檔案另存為uf-8格式就行了

一行程式碼太長怎麼辦?
用“\”符號就行了!

第七週

  1. 檔案操作
    <變數名> = open(<檔名>,<開啟模式>)
    檔案最好跟程式在同一個目錄下,這樣就不用再指定檔案地址
    檔案開啟模式主要有以下幾種:
    在這裡插入圖片描述
    使用具體方法
    在這裡插入圖片描述

檔案關閉:<變數名>.close()
檔案一旦被開啟,如果沒有對應的關閉語句就是在程式中一直被開啟,只有在程式退出時才會被自動關閉
2. 檔案內容讀取

操作方法 描述
<檔名>.read(size=-1) 讀入全部內容,如果給出引數,讀入前size長度,size為2,就是讀前兩個字元
<檔名>.readline(size=-1) 讀入一行內容,如果給出引數,讀入改行前size長度,size為2,就是讀改行前兩個字元
<檔名>.readlines(hint=-1) 讀入檔案所有行,以每行行為元素形成列表,如果給出引數,讀入前hint行
  1. seek()內建函式
    引數為0:指標回到檔案開頭
    引數為1:指標回到當前位置
    引數為2:指標回到檔案結尾
  2. 檔案寫的時候注意事項:

fo = open(“ls.txt”,"w+)# 開啟檔案,文字形式,覆蓋寫模式+讀檔案
fo.writelines(ls)# 讀入檔案所有行
fo.seek(0)# 將指標退回到檔案開頭
for line on fo:# 逐行列印
print(line)
fo.close#檔案關閉

fo.seek(0)# 將指標退回到檔案開頭這一步非常重要,如果沒有退回指標,那麼打印出來的就沒有結果。
上面這個程式也給出了遍歷全文的一種常用的程式碼模板,要牢記。

檔案驅動繪圖程式

import turtle
turtle.title("資料驅動繪圖")
turtle.color("red")
turtle.setup(800,800)
turtle.pensize(5)

# 資料獲取,一組五個引數
# 300,0,144,1,0,0
# 前進距離,(0:左轉,1:右轉),轉向的絕對角度,rgb對應的三個引數(0-1之間的小數)
data = []
f = open("datals.txt")
for line in f:
    line = line.replace("\n", " ")
    data.append(list(map(eval,line.split(","))))
f.close()
# 繪圖
for i in range(len(data)):
    turtle.fd(data[i][0])
    turtle.color(data[i][3], data[i][4], data[i][5])
    if data[i][1]:
        turtle.right(data[i][2])
    else:
        turtle.left(data[i][2])
        

首次使用檔案驅動程式,將資料與程式分離,建立介面大大提高了程式碼的適應性。麻煩的是需要將輸入的資料進行處理。該程式中資料處理關鍵語句:

for line in f:
    line = line.replace("\n", " ")
    data.append(list(map(eval,line.split(","))))

資料傳輸進來,首先就將該行的換行符換為空格。然後資料是以字串的形式傳進來,使用spilt()函式將整個大的字串資料,使用逗號“,”進行分隔成小的字串。然後為了程式處理的資料均為數字,再使用eval函式將每個小的字串去掉引號變成數字。(map(a,b)函式就是使用a函式對b中的每個元素進行函式操作。)再使用list將轉化為數字的資料變成一個列表。最後使用append函式將輸入檔案的每一行進行拼接。最後形成的就是類似這種結構[[],[],[],[],[]]的一個列表。

  1. str.join(元組、列表、字典、字串)
    用想要的符號進行分隔

list=[‘1’,‘2’,‘3’,‘4’,‘5’]
print(’’.join(list))
12345

  1. wordcloud
    安裝詞雲 :pip install wordcloud
    構建詞雲物件

class wordcloud.WordCloud(font_path=None, width=400, height=200, margin=2, ranks_only=None, prefer_horizontal=0.9, mask=None, scale=1, color_func=None, max_words=200, min_font_size=4, stopwords=None, random_state=None, background_color=‘black’, max_font_size=None, font_step=1, mode=‘RGB’, relative_scaling=0.5, regexp=None, collocations=True, colormap=None, normalize_plurals=True)

引數 型別 描述
font_path string 指定字型的位置(可以在網上下載OTF或者TTF格式),預設使用DroidSansMono path
width int(default=400) 圖片寬度,越大越精細
height int (default=200) 圖片高度,越大越精細
prefer_horizontal float (default=0.90) 越接近1說明越喜歡水平的字,則字就不會為了適合展示而翻轉成水平的
mask : nd-array or None (default=None) 將詞雲畫在遮罩上
scale : float (default=1) 計算和畫圖的比例,當做大圖的時候使用scale代替height和width速度會快,但會影響詞之間的擬合度
min_font_size : int (default=4) 最小頻率詞的大小
font_step : int (default=1) 字型步長,如果大於1,可以增快計算速度,但是擬合度會下降
max_words : number (default=200) 圖片容納詞語的上限
stopwords : set of strings or None 設定停用詞,如果不設定則使用預設的停用詞
background_color : color value (default=”black”) 背景顏色設定
max_font_size : int or None (default=None) 最大的詞語的大小
mode : string (default=”RGB”) 當使用”RGBA”時,背景將變成透明的
relative_scaling : float (default=.5) 當relative_scaling=0時,詞的大小是按照排名計算的,當relative_scaling=1時候則會按詞頻的倍數計算大小。
color_func : callable, default=None 根據每個詞的font_size, position, orientation, font_path, random_state等屬性為詞語生成特定的顏色,具體參考matplotlib colormap
regexp : string or None (optional)
collocations : bool, default=True 是否考慮詞語的搭配
colormap : string or matplotlib colormap, default=”viridis” Matplotlib colormap,如果color_func引數被指定,則此引數無效
normalize_plurals : bool, default=True 是否忽略複數
words_ (dict of string to float) 返回詞頻
layout_ (list of tuples (string, int, (int, int), int, color))) 詞雲詞的屬性資訊

詞雲源程式

import jieba
import wordcloud
from scipy.misc import imread
mask = imread("china.png")
f = open("新時代中國特色社會主義.txt","r",encoding="utf-8")
t = f.read()
f.close()
# 將輸入的詞用空格分隔,才能被識別
ls = jieba.lcut(t)
txt = " ".join(ls)
# 設定引數
w = wordcloud.WordCloud(font_path="msyh.ttc",mask=mask,\
                        width=1000, height=700, background_color = "white")
w.generate(txt)# 生成詞雲
w.to_file("grwordcloud.png")# 輸出生成的詞雲圖片

只實現了最最基本的內容,而且scrip這個庫需要匯入,且遇到了版本太低的問題,而且圖片的匯入方式也不好,使用image庫可能處理更加規範方便。
於是自行編寫了以下程式:

import jieba
import wordcloud
from matplotlib import pyplot as plt
from  PIL import Image
import numpy as np


# 文字輸入格式化
def word_txt(txt):
    f = open(txt, "r" ,encoding="utf-8")# 開啟檔案
    t = f.read()
    f.close()
    ls = jieba.lcut(t)# 將輸入的詞用空格分隔,才能被識別
    txt = " ".join(ls)
    return txt


# 讀入背景圖片
def image_deal(img):
    img = Image.open(img)
    img_array = np.array(img)# 將圖片轉化成陣列
    return img_array

# 設定詞雲的引數
def wordcloud_set():
    word = wordcloud.WordCloud( font_path="simsun.ttc",\
                        mask = image_deal('wade6.jpg'),\
                        width=800, height=800,\
                        background_color = "black",\
                        stopwords=[],\
                        max_words=1000, \
                        min_font_size=5,\
                        max_font_size=200,\
                        scale=10,\
                        random_state=50)
    return word

word = wordcloud_set()
word.generate(word_txt('新時代中國特色社會主義.txt')) # 生成詞雲
word.to_file("grwordcloud.png")# 輸出生成的詞雲圖片
plt.imshow(word)
plt.axis('off')
plt.show()

第八週

1 Python庫安裝
第三方安裝庫網站:http://pypi.org/
三種方法:
方法一(主要方法,需要聯網):使用pip命令
電腦自帶cmd命令下進行操作:

作用 操作方法
安裝庫 pip install <第三方庫名>
更新庫 pip install -U<第三方庫名>
解除安裝庫 pip uninstall <第三方庫名>
檢視庫的詳細資訊 pip show <第三方庫名>
根據關鍵詞在名稱和介紹中搜索第三方庫 pip search <關鍵詞>

方法二:整合安裝方法
*Anaconda :https//www.continuum.io
*支援800個第三方庫
*包含多個主流工具
*適合資料計算領域開發
方法三:檔案安裝方法
對於有些庫可以用pip下載,但是不能安裝,為什麼?
由於某些第三方庫下載後,需要編譯再安裝,如果作業系統沒有編譯環境,則能下載但不能安裝。
解決辦法:
在這裡插入圖片描述

模擬比賽源程式

import random
import time
def printInformation():
    print("程式模擬A和B兩個運動員之間的競技比賽")
    print("程式輸入為A、B選手的能力值(0至1之間的小數)及模擬場數N")


def getvalue():
    player_a = eval(input("請輸入A選手能力值:"))
    player_b = eval(input("請輸入B選手能力值:"))
    N = eval(input("請輸入模擬場數:"))
    return player_a, player_b, N


def play_one_game(ability_a, ability_b, star_game):
    time.sleep(0.0001)
    a_win, b_win = 0, 0
    random_num = random.random()
    if star_game == "a" and (random_num < ability_a):
        a_win = 10.
        nx_star_game = "a"
    elif star_game == "a" and (random_num > ability_a):
        a_win = 0
        nx_star_game = "b"
    elif star_game == "b" and (random_num < ability_b):
        b_win = 1
        nx_star_game = "b"
    elif star_game == "b" and (random_num > ability_b):
        b_win = 0
        nx_star_game = "a"
    return a_win, b_win, nx_star_game


def play_n_game(ability_a, ability_b, n):
    num_a, num_b = 0, 0
    star_game = "a"
    while num_a + num_b != n :
        a_win, b_win, nx_star_game = play_one_game(ability_a, ability_b, star_game)
        num_a += a_win
        num_b += b_win
        star_game = nx_star_game
    return num_a, num_b


def result(num_a, num_b):
    n = num_a + num_b
    print("共模擬{}場比賽".format(n))
    print("選手A贏得{}場,勝率為:{:.1f}%".format(num_a, num_a*100/n))
    print("選手B贏得{}場,勝率為:{:.1f}%".format(num_b, num_b*100/n))


def main():
    printInformation()
    ability_a, ability_b, n = getvalue()
    num_a, num_b = play_n_game(ability_a, ability_b, n)
    result(num_a, num_b)


main()

程式碼與視訊中的程式碼存在不同,是我自己看完寫的,沒有用視訊的。
值得注意的是random()函式在最開始使用的for迴圈中出現了產生相同隨機數的情況。也就是第四周中提到的偽隨機數,我的解決辦法是在函式中插入time.sleep(time),由於在不指定隨機數種子的情況下,random()使用的是系統時間作為種子,時間精度為微秒。因此我進行sleep一定時間後再取隨機數即可。看網上大神有更專業的處理方式或者不將其放到for迴圈之中,但是由於程式比較簡單那就用簡單一些的方式處理吧。