SQlALchemy session詳解

系列文章:

概念

session用於創建程序和數據庫之間的會話,所有對象的載入和保存都需通過session對象 。

通過sessionmaker調用創建一個工廠,並關聯Engine以確保每個session都可以使用該Engine連接資源:

from sqlalchemy.orm import sessionmaker

# 創建session
DbSession = sessionmaker(bind=engine)
session = DbSession()

操作

session的常見操作方法包括:

  1. flush:預提交,提交到數據庫文件,還未寫入數據庫文件中
  2. commit:提交了一個事務,把內存的數據直接寫入數據庫
  3. rollback:回滾
  4. close:關閉

在事務處理時,需注意一下兩點:

  1. 在事務處理過程發生異常時,進行rollback操作,否則會在下次操作時報錯:
Can’t reconnect until invalid transaction is rolled back 
  1. 一般情況下,在一個事務處理完成之後要關閉session,以確保數據操作的準確性。

建議封裝上下文方法:

from contextlib import contextmanager

@contextmanager
def session_maker(session=session):
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()

調用:

def update_user():
    with session_maker() as db_session:
        db_session.query(Users).filter_by(name='test2').update({'email': 'test2@qq.com'})

線程安全

session不是線程安全的,並且我們一般session對象都是全局的,那麼在多線程情況下,當多個線程共享一個session時,數據處理就會發生錯誤。

為了保證線程安全,需使用scoped_session方法:

db_session = scoped_session(sessionmaker(bind=engine))

內部原理

session對象包含了三個重要的部分:

  1. 標識映射(Identity Map)
  2. 對象的狀態 / 狀態跟蹤
  3. 事務

標識映射

標識映射是與ORM關聯的集合,通過標識映射保證了數據庫操作的準確性。

具體的實現原理是:維護一個Python字典(IdentityMap),關聯這個Session對象到數據庫ID的映射,當應用程序想要獲取一個session對象時,若該對象不存在,標識映射會加載該對象並緩存,若該對象已存在,則直接獲取。這樣的好處是:

  1. 已經被請求過的session對象緩存下來,不需要連接加載多次,造成額外的開銷;
  2. 避免了數據不一致

狀態跟蹤

一個Session對象從創建到銷毀,依次經歷四種狀態,分別是:

  1. Transient:剛new出來的對象,還不在會話中,也沒有保存到數據庫。
  2. Pending:transient的對象調用add后,就會變成pending狀態,這時會加入sqlalchemy的監管範圍,數據並未更新到數據庫。
  3. Persistent:該狀態表明數據庫里已經記錄了該對象,在兩種情況下對象處於該狀態:一是通過flush()方法刷新pending對象,二是從數據庫query()得到對象。
  4. Detached:在會話中的事務提交之後,所有的對象都將是Detached狀態。

所謂的狀態跟蹤,就是跟蹤以上四個狀態,保證數據的準確性並在合理的時機丟棄對象以保證合理開銷,那麼具體是怎麼實現的呢?

我們可以看到,只有在pending狀態時,對象的內存數據和數據庫中的數據不一致,在Persistent狀態時,內存數據和數據庫數據已經一致,那麼此後任意時刻丟棄該對象數據都是可以的,這時就需要找個合適的時機丟棄對象,過早或過晚都有其缺陷。於是,就讓垃圾回收器來做決定,在內存不夠的時候釋放對象,回收內存。

Session對象採用了弱引用機制,所謂弱引用,就是說,在保存了對象的引用的情況下,對象仍然可能被垃圾回收器回收。在某一時刻通過引用訪問對象時,對象可能存在也可能不存在,如果對象不存在,就重新從數據庫中加載對象。而如果不希望對象被回收,只需要另外保存一個對象的強引用即可 。

session對象包括三個屬性:

  1. new:剛加入會話的對象
  2. dirty:剛被修改的對象
  3. deleted:在會話中被刪除的對象

三個屬性共同的特點就是內存的數據和數據庫數據不一致,也就是對象處於pending狀態,這也就表明了session保存了所有對象處於pending狀態的強引用。

以上。

代碼可參照:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

從演奏家的新年大膽願望 一窺日本都市蜂害問題

文:宋瑞文

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

巴西東南部暴雨成災 總統視察下令撥款救援

摘錄自2020年1月31日中央社報導

巴西東南部米納斯吉拉斯、聖埃斯皮里圖和里約熱內盧三州本月遭暴雨侵襲,巴西總統波索納洛今(30日)視察受災最嚴重的城市之一好景市,宣布聯邦政府將撥款巴西幣9億元賑災。

1889年建城的好景市層獲聯合國評為「環境模範市」,同時被譽為「花園城」,1980年代市內綠地範圍和居民人口比例一度高達32平方公尺比1,但現在卻到處都是不透水的柏油路面,暴雨襲擊不僅引發嚴重淹水,道路更慘遭摧毀,出現坑洞、隆起現象。

聖保羅大學(USP)氣象學家安布里茲(Tercio Ambrizzi)指出,今年夏天南大西洋海水變暖,使得南極上來的冷氣團在巴西東南部停留更長時間,加上熱帶低壓帶來強烈雨勢,特別是米納斯吉拉斯、聖埃斯皮里圖和里約熱內盧三州持續多雨,土壤和岩層沒有足夠時間吸收水分,也容易引發土石流。

24日迄今,包括好景市在內,米納斯吉拉斯州已有101個城市處於緊急狀態,另外五個城市宣布進入公共災難狀態,超過5萬人流離失所,55人死亡。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

原來JS是這樣的 – 原型鏈

提到屬性描述符 [[Get]][[Put]] 以及提到了訪問描述符 [[Prototype]],看它們的特性就會很容易的讓人想到經典的面向對象風格體系中對類操作要做的事情,但帶一些 introspector 的味道。回想到之前所寫來自用的辣雞應用中所附帶了一個簡易的類似 jQuery 的簡易常用功能實現,就用到了簡單的 [[Prototype]] 特性。但我們前幾篇都沒有詳細的提及 js 的原型鏈相關的內容,本篇就將討論 js 的 [[Prototype]] 屬性和相關的內容。

注:ES6 的 Proxy 和 class 的概念不在本篇討論範圍內。

[[Prototype]]

JavaScript 中的特殊對象屬性除了 [[Get]][[Put]] 外,還有一個很重要的特殊內置屬性就是 [[Prototype]] 了。

[[Prototype]] 是一個幾乎所有對象在創建時都會被賦予一個非空值的屬性,還記得在之前提到 new 操作符的行為嗎?其中的行為之一就是把其 [[Prototype]] 關聯指向到對應的內置對象上。通常 [[Prototype]] 所指向的即為創建此對象時所使用的對象了。

來看下面一個例子

var macat = { a: 1 };

var codingcat = macat; // 和 macat 指向的內容相同
codingcat.b = 2;
console.log(macat.b); // 2

var pineapple = Object.create( macat ); // 新對象,但其 [[Prototype]] 鏈向 macat
pineapple.c = 3; // 新對象的屬性
console.log(macat.c); // undefined
codingcat.d = 4;
console.log(pineapple.d) // 4;

上例中, 變量 codingcat 顯然是指向和 macat 相同的內容,實質完全一致,而 pineapple 則是通過 創建的變量。顯然 pineapplemacat 是不同的兩個對象。不過我們會發現我們依然可以通過 pineapple.d 訪問 macat.d 的值,這就是因為在 Object.create() 中,會把 pineapple[[Prototype]] 指向我們的原型對象 macat 了。

[[Prototype]] 引用的作用是什麼呢?看上去這是一個確定這種像 fallback 一樣的取值操作應該 fallback 到誰的屬性標記,而準確的說,這種 pineapple.d 形式的屬性引用會觸發 [[Get]] 操作(上篇的內容),而默認的 [[Get]] 則會在對象本身沒有此屬性時會去查找 [[Prototype]] 引用的變量了。這樣的引用成為了鏈狀,故被稱作原型鏈。

當然,這個行為其實我們已經“用過”很多次了,比如 .toString().valueOf()hasOwnProperty(),我們 Object.create() 等形式構建的新對象顯然並沒有附帶一份這些函數的副本,而是因為普通的 [[Prototype]] 鏈最終都會指向內置的 Object.prototype,而它提供了這些功能。

屬性設置和屏蔽

不過上例中有個有趣的坑,我們考慮在上例的基礎上做如下操作:

...
pineapple.a++; // 交互式終端會輸出 1
console.log(pineapple.a); // 2
console.log(macat.a); // 1

pineapple.a++ 看上去是進行了變量自增的操作,但這一行后,我們發現 pineapple.a 不再等於 macat.a 了,這是因為實際上 pineapple.a 本來並不存在,但可以通過原型鏈找到 macat.a,而 pineapple.a++ (相當於 pineapple.a = pineapple.a + 1)最終進行的賦值操作創建了 pineapple.a ,故最終這兩個變量的值自然不再相等。

這個例子來看,如果本身即通過對 pineapple 的屬性(a)進行訪問操作,那麼不同情況下訪問得到的結果可能是不同的甚至是出人意料的。無意中創建的屬性“阻止”了原型鏈上查找這個屬性的行為,我們稱之為屬性屏蔽

屬性屏蔽根據變量本身情況的不同會有很多不同的狀態表現,例如原型鏈上層變量的數據訪問屬性標記為只讀的情況,(如果不是嚴格模式下)嘗試進行的賦值操作會被忽略等。

類 (迫真)

我們早已知道 JavaScript 中不存在“類”的概念,而為了能夠“寫着爽”,很多開發者都在想盡辦法在 JavaScript 中模仿其它 OO 語言中“類”的行為。其中很常見的做法類似下面這樣:

function Person(name) {
    console.log("I'm " + name + "!");
    this.name = name;
}

Person.prototype.getName = function() {
    return this.name;
}

var chris = new Person("Chris"); // I'm Chris
var sophie = new Person("Sophie"); // I'm Sophie
chris.getName(); // "Chris"

看上去我們的 Person 像極了一個包含 name 成員變量和 getName() 方法的類,並且在其“構造函數”中會輸出 “I’m xxx”。不過在之前的文章中我們已經講過了,並不存在所謂的構造函數,new 只是把 Person() 函數作為構造對象所需調用的函數進行了一次調用而已。不過你可能還會比較奇怪為什麼 .getName() 是可以使用的,既然我們在原型鏈這一章提起這件事,顯然是因為原型鏈,於是回顧之前第二章我們含糊提到的一句話是(之一是)“對這個新對象執行 [[Prototype]] 鏈接”,實際上,這裏我們被 new 出來的對象的 [[Prototype]] 被關聯到了 Person.prototype 上,於是當我們嘗試進行屬性訪問的時候,自然就可以訪問到 Person.prototype.getName() 上了。

不過這個過程還是可能會引起一些蛋疼的誤會,比如假設我們在上面例子的基礎上:

...
sophie.constructor === Person; // true
sophie.constructor === Person.prototype.constructor; // true
Person.prototype = {};
var koishi = new Person("Koishi");  // I'm Koishi
koishi.constructor === Person; // false
koishi.constructor === Object; // true
sophie.constructor === Person; // true
sophie.constructor === Person.prototype.constructor; // false

由於“構造函數”這種表現形式的理解,我們有時候會認為 變量名.constructor 實際就總是構造調用時指向的函數,甚至 sophie.constructor === Person 返回也是 true ,但實際並不是這樣,這裏返回為真,僅僅是因為 Person.prototype.constructor 默認指向的就是 Person 罷了。於是我們嘗試替換 Person.prototype 之後創建了變量 koishi,再檢查 koishi.constructor === Person 就不再為真了,在原型鏈的查找過程最終找到了 Object.prototype,然後 Object.prototype.constructor 其實指向了 Object

不過,後面我們接着嘗試檢查了 sophie.constructor 卻發現似乎它並未受到影響,這個就不要往原型鏈方面想了,這裏的原因僅僅是 sophie 的原型鏈指向的是曾經 Person.prototype 所指向的東西上,而我們 Person.prototype = {} 的操作只是讓 Person.prototype 指向了新的東西,舊的東西並沒有改變,所以 sophie 自然看上去“沒有受到影響”了。當然,koishi 這個變量被構造時所被調用的函數仍然是 Person(),這和 koishi.constructor 或者 Person.prototype.constructor 的指向沒有什麼關係。

對象實例關係

當然我們還有一點需要重新強調的是,[[Prototype]].prototype 不是一回事,[[Prototype]] 是描述對象實例關係的屬性描述符,而 .prototype 只是 Function 對象的一個屬性而已。new 操作符會把新建的對象的 [[Prototype]] 指向原對象的 .prototype 屬性上,僅此而已。

既然 [[Prototype]] 實際描述了對象之間的實例關係,那麼我們自然就可以想到 instanceof 的實際作用了,其所做的事情就是告訴你在 a instanceof Foo 中, a 的整個原型鏈中是否有指向 Foo.prototype 的對象。

絕大多數瀏覽器支持一個 .__proto__ 屬性(實際位於 Object.__proto__)指向了 [[Prototype]] ,這對於我們調試時希望直接訪問內部的 [[Prototype]] 提供了便利,不過它並不是標準,所以除了調試便利之外還是不要使用它比較好。

最後

於是關於原型鏈相關的簡單討論就到此結束了。和上篇一樣,如果你對這些內容仍然感興趣,不妨去讀一讀《You don’t know JS – this & object prototypes》一書。這是一本開源書,你可以在這裡在線閱讀這本書,或者購買這本書的电子版或實體版。這本書的中文譯本涵蓋在《你所不知道的 JavaScript 上卷》中,你也可以考慮看中文版。

由於近期工作過於繁忙的精力佔用緣故,“原來JS是這樣的”系列可能就暫時告一段落了。最後,儘管我會盡可能仔細的檢查文章內容是否有問題,但也不保證這篇文章中一定不會有錯誤,如果您發現文章哪裡有問題,請在下面留言指正,或通過任何你找得到的方式聯繫我指正。感激不盡~

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

中介者模式

2019年11月11日08:45:25

中介者模式(mediator pattern)

定義

從前的日色變得慢

車,馬,郵件都慢

一生只夠愛一個人

中介者模式(mediator pattern),用一个中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地互相引用,從而使其耦合鬆散,而且可以獨立地改變它們的交互。————《設計模式:可復用面向對象軟件的基礎》

中介者模式是一種對象行為型模式。

從木心這首小詩中的“郵件”中,討論一下中介者模式。

很久很久以前,你和她住在一個很大很大的村子裏面,你住在村的東邊,她住在村的西邊。

那年你才十八,她也正值青春年華,正月十五元宵節,你賞燈之時,她回首處,你一見鍾情。

往後的日子里,你每天都到她家送情書。送了99天,你想這不是辦法,每天大半天浪費在路上,沒時間賺錢。於是你想了一個辦法,創辦郵局,每天替村東邊的人送信件給村西邊的人,一舉兩得。慢慢郵局越來越大,南邊的人通過郵局來給北邊的人送信件,你找了幾個夥計,從南到北,從北到南送信。

多年後,你富甲一方,也娶了當年的她。

“郵局”就是中介者模式中的中介者,“你”和“她”就是中介者中的同事。

圖示

中介者模式結構圖:

角色

從中介者模式結構圖中可知,有以下4個角色:

  • (1)抽象中介者:定義了中介者
  • (2)具體中介者:實現了抽象中介者的方法,它需要知道所有具體同事對象,並從具體同事對象接收消息,向具體同事對象發出命令。
  • (3)抽象同事類:定義同事類
  • (4)具體同事類:實現抽象同事類,每個具體同事對象只知道自己的行為,而不了解其他同事對象的情況,但它們都認識中介者。

代碼示例

這是一個悲傷的故事,住在村東邊的你通過郵局給村西邊的她表白,她說,她已經有男朋友了。

類圖:

抽象中介者角色:

public interface PostOffice {
    /**
     * 送信
     */
    void deliverLetters(String letters, String receiver);

    /**
     * 添加收信人
     */
    void addPeople(Villager villager);
}

具體中介者角色:

public class PostOfficeImpl implements PostOffice {
    /**
     * 收信人信息
     */
    private HashMap villagerMap = new HashMap<String, Villager>();

    @Override
    public void addPeople(Villager villager) {
        villagerMap.put(villager.getClass().getSimpleName(), villager);
    }

    @Override
    public void deliverLetters(String letters, String receiver) {
        System.out.println("=>收信:郵局收到要寄的信");
        Villager villager = (Villager) villagerMap.get(receiver);
        System.out.println("=>送信:拿出地址本查詢收信人地址是:" + villager.getAddress() + ",送信");
        System.out.println("=>收信人看信:");
        villager.receiveLetter(letters);
    }
}

抽象同事類角色:

public abstract class Villager {
    protected PostOffice postOffice;
    protected String address;

    Villager(PostOffice postOffice, String address) {
        this.postOffice = postOffice;
        this.address = address;
    }

    public void receiveLetter(String letter) {
        System.out.println(letter);
    }

    public void sendLetter(String letter, String receiver) {
        postOffice.deliverLetters(letter, receiver);
    }

    public String getAddress() {
        return address;
    }
}

具體同事類角色:

// 她
public class She extends Villager {

    She(PostOffice postOffice, String address) {
        super(postOffice, address);
    }
}
// 你
public class You extends Villager {
    public You(PostOffice postOffice, String address) {
        super(postOffice, address);
    }
}

中介者模式測試類:

public class MediatorPatternTest {
    public static void main(String[] args) {
        PostOffice postOffice = new PostOfficeImpl();
        She she = new She(postOffice, "村西邊");
        You you = new You(postOffice, "村東邊");

        postOffice.addPeople(she);
        postOffice.addPeople(you);

        you.sendLetter("正月十五,元宵之夜,一見傾心", "She");
        she.sendLetter("對不起,我已經有男朋友了", "You");
    }
}

測試結果:

使用場景

村子很大,人很多,關係很複雜:系統中存在很多對象,對象之間存在複雜的引用關係,產生的相互依賴關係結構混亂且難以理解,使得對象無法重用

人與人之間書信交流:對象間存在某種共性交互行為,用中介者封裝這種行為

在這個很大的村子裏面,每個人要給不同人的送信,這種關係成網狀結構,錯綜複雜。

加入郵局中介者之後,成星狀結構,每個人只和郵局有關係。

總結:系統中存在很多對象,對象間存在複雜的關係,在複雜的關係中存在共性交互行為,封裝共性交互行為就是中介者。

中介者模式很容易在系統中應用,也很容易在系統中無用。當系統出現了“多對多”交互複雜的對象群是,不要急於使用中介者模式,而要先反思你的系統在設計上是不是合理。

實例有:聯合國,聊天室等。

中介者模式與迪米特法則

中介者模式是應用迪米特法則的典型。

迪米特法則:只與你最直接的朋友交流(Only talk to you immediate friends.)參考

優點

  • 解耦:使同事類對象耦合性降低,可以獨立變化和復用同事類
  • 把對象如何協作進行了抽象,將中介作為一個獨立的概念並將其封裝在一個對象中,這樣關注的對象就從對象各自本身的行為轉移到它們之間的交互上來,也就是在一個更宏觀的角度看待系統。

缺點

  • 在具體中介者類中包含了同事之間的交互細節,可能會導致具體中介者類非常複雜,不利於維護,後期可能有牽一發而動全身的危險。

總結

中介者模式,用一个中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地互相引用,從而使其耦合鬆散,而且可以獨立地改變它們的交互。

2019年11月17日16:32:36

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

(數據科學學習手札71)利用Python繪製詞雲圖

本文對應腳本及數據已上傳至我的Github倉庫

一、簡介

  詞雲圖是文本挖掘中用來表徵詞頻的數據可視化圖像,通過它可以很直觀地展現文本數據中地高頻詞:


圖1 詞雲圖示例

  在Python中有很多可視化框架可以用來製作詞雲圖,如,但這些框架並不是專門用於製作詞雲圖的,因此並不支持更加個性化的製圖需求,要想創作出更加美觀個性的詞雲圖,需要用到一些專門繪製詞雲圖的第三方模塊,本文就將針對其中較為優秀易用的以及的用法進行介紹和舉例說明。

二、利用wordcloud繪製詞雲圖

  wordcloud是Python中製作詞雲圖比較經典的一個模塊,賦予用戶高度的自由度來創作詞雲圖:


圖2 wordcloud製作詞雲圖示例

2.1 從一個簡單的例子開始

  這裏我們使用到來自wordcloud官方文檔中的constitution.txt來作為可視化的數據素材:


圖3 constitution.txt

  首先我們讀入數據並將數據清洗成空格分隔的長字符串:

import re

with open('constitution.txt') as c:
    '''抽取文本中的英文部分並小寫化,並將空格作為分隔拼接為長字符串'''
    text = ' '.join([word.group().lower() for word in re.finditer('[a-zA-Z]+', c.read())])

'''查看前100個字符'''
text[:500]

圖4 清洗后的片段文本

  接着使用wordcloud中用於生成詞雲圖的類WordCloud配合matplotlib,在默認參數設置下生成一張簡單的詞雲圖:

from wordcloud import WordCloud
import matplotlib.pyplot as plt
%matplotlib inline

'''從文本中生成詞雲圖'''
wordcloud = WordCloud().generate(text)
plt.figure(figsize=[12, 10])
plt.imshow(wordcloud)
plt.axis('off')
plt.show()

  生成的詞雲圖:


圖5 默認參數下的詞雲圖

  畢竟是在默認參數下生成的詞雲圖,既醜陋又模糊,為了繪製好看的詞雲圖,接下來我們來對wordcloud繪製詞雲圖的細節內容進行介紹,並不斷地對圖5進行升級改造。

2.2 WordCloud

  作為wordcloud繪製詞雲圖最核心的類,WordCloud的主要參數及說明如下:

font_path:字符型,用於傳入本地特定字體文件的路徑(ttf或otf文件)從而影響詞雲圖的字體族
width:int型,用於控制詞雲圖畫布寬度,默認為400
height:int型,用於控制詞雲圖畫布高度,默認為200
prefer_horizontal:float型,控制所有水平显示的文字相對於豎直显示文字的比例,越小則詞雲圖中豎直显示的文字越多
mask:傳入蒙版圖像矩陣,使得詞雲的分佈與傳入的蒙版圖像一致
contour:float型,當mask不為None時,contour參數決定了蒙版圖像輪廓線的显示寬度,默認為0即不显示輪廓線
contour_color:設置蒙版輪廓線的顏色,默認為’black’
scale:當畫布長寬固定時,按照比例進行放大畫布,如scale設置為1.5,則長和寬都是原來畫布的1.5倍
min_font_size:int型,控制詞雲圖中最小的詞對應的字體大小,默認為4
max_font_size:int型,控制詞雲圖中最大的詞對應的字體大小,默認為200
max_words:int型,控制一張畫布中最多繪製的詞個數,默認為200
stopwords:控制繪圖時忽略的停用詞,即不繪製停用詞中提及的詞,默認為None,即調用自帶的停用詞表(僅限英文,中文需自己提供並傳入)
background_color:控制詞雲圖背景色,默認為’black’
mode:當設置為’RGBA’且background_color設置為None時,背景色變為透明,默認為’RGB’
relative_scaling:float型,控制詞雲圖繪製字的字體大小與對應字詞頻的一致相關性,當設置為1時完全相關,當為0時完全不相關,默認為0.5
color_func:傳入自定義調色盤函數,默認為None
colormap:對應matplotlib中的colormap調色盤,默認為viridis,這個參數與參數color_func互斥,當color_func有函數傳入時本參數失效
repeat:bool型,控制是否允許一張詞雲圖中出現重複詞,默認為False即不允許重複詞
random_state:控制隨機數水平,傳入某個固定的数字之後每一次繪圖文字布局將不會改變

  了解了上述參數的意義之後,首先我們修改背景色為白色,增大圖床的長和寬,加大scale以提升圖片的精細程度,並使得水平显示的文字盡可能多:

'''從文本中生成詞雲圖'''
wordcloud = WordCloud(background_color='white', # 背景色為白色
                      height=400, # 高度設置為400
                      width=800, # 寬度設置為800
                      scale=20, # 長寬拉伸程度設置為20
                      prefer_horizontal=0.9999).generate(text)
plt.figure(figsize=[8, 4])
plt.imshow(wordcloud)
plt.axis('off')
'''保存到本地'''
plt.savefig('圖6.jpg', dpi=600, bbox_inches='tight', quality=95)
plt.show()

圖6

  可以看到相較於圖5,在美觀程度上有了很大的進步,接下來,我們在圖6的基礎上添加美國本土地圖蒙版:


圖7 美國本土地圖蒙版

  利用PIL模塊讀取我們的美國本土地圖蒙版.png文件並轉換為numpy數組,作為WordCloud的mask參數傳入:

from PIL import Image
import numpy as np

usa_mask = np.array(Image.open('美國本土地圖蒙版.png'))

'''從文本中生成詞雲圖'''
wordcloud = WordCloud(background_color='white', # 背景色為白色
                      height=4000, # 高度設置為400
                      width=8000, # 寬度設置為800
                      scale=20, # 長寬拉伸程度程度設置為20
                      prefer_horizontal=0.9999,
                      mask=usa_mask # 添加蒙版
                     ).generate(text)
plt.figure(figsize=[8, 4])
plt.imshow(wordcloud)
plt.axis('off')
'''保存到本地'''
plt.savefig('圖8.jpg', dpi=600, bbox_inches='tight', quality=95)
plt.show()

圖8

  可以看到圖8在圖6的基礎上進一步提升了美觀程度,接下來我們利用wordcloud中用於從圖片中提取調色方案的類ImageColorGenerator來從下面的星條旗美國地圖蒙版中提取色彩方案,進而反饋到詞雲圖上:


圖9 美國地圖蒙版_星條旗色

from PIL import Image
import numpy as np
from wordcloud import ImageColorGenerator

usa_mask = np.array(Image.open('美國地圖蒙版_星條旗色.png'))
image_colors = ImageColorGenerator(usa_mask)

'''從文本中生成詞雲圖'''
wordcloud = WordCloud(background_color='white', # 背景色為白色
                      height=400, # 高度設置為400
                      width=800, # 寬度設置為800
                      scale=20, # 長寬拉伸程度程度設置為20
                      prefer_horizontal=0.2, # 調整水平显示傾向程度為0.2
                      mask=usa_mask, # 添加蒙版
                      max_words=1000, # 設置最大显示字數為1000
                      relative_scaling=0.3, # 設置字體大小與詞頻的關聯程度為0.3
                      max_font_size=80 # 縮小最大字體為80
                     ).generate(text)

plt.figure(figsize=[8, 4])
plt.imshow(wordcloud.recolor(color_func=image_colors), alpha=1)
plt.axis('off')
'''保存到本地'''
plt.savefig('圖10.jpg', dpi=600, bbox_inches='tight', quality=95)
plt.show()

圖10

2.3 中文詞雲圖

  相較於英文文本語料,中文語料處理起來要麻煩一些,我們需要先進行分詞等預處理才能進行下一步的處理,這裏我們使用,先讀取進來看看:

import pandas as pd
import jieba

'''讀入原始數據'''
raw_comments = pd.read_csv('waimai_10k.csv');raw_comments.head()

圖11

  接下來我們利用rejieba以及pandas中的apply對評論列進行快速清洗:

'''導入停用詞表'''
with open('stopwords.txt') as s:
    stopwords = set([line.replace('\n', '') for line in s])

'''傳入apply的預處理函數,完成中文提取、分詞以及多餘空格剔除'''
def preprocessing(c):
    
    c = [word for word in jieba.cut(' '.join(re.findall('[\u4e00-\u9fa5]+', c))) if word != ' ' and word not in stopwords]

    return ' '.join(c)

'''將所有語料按空格拼接為一整段文字'''
comments = ' '.join(raw_comments['review'].apply(preprocessing));comments[:500]

  得到的結果如圖12:


圖12

  這時我們就得到所需的文本數據,接下來我們用美團外賣的logo圖片作為蒙版繪製詞雲圖:


圖13 美團外賣logo蒙版

from PIL import Image
import numpy as np
from wordcloud import ImageColorGenerator

waimai_mask = np.array(Image.open('美團外賣logo蒙版.png'))
image_colors = ImageColorGenerator(waimai_mask)

'''從文本中生成詞雲圖'''
wordcloud = WordCloud(background_color='white', # 背景色為白色
                      height=400, # 高度設置為400
                      width=800, # 寬度設置為800
                      scale=20, # 長寬拉伸程度程度設置為20
                      prefer_horizontal=0.2, # 調整水平显示傾向程度為0.2
                      mask=waimai_mask, # 添加蒙版
                      max_words=1000, # 設置最大显示字數為1000
                      relative_scaling=0.3, # 設置字體大小與詞頻的關聯程度為0.3
                      max_font_size=80 # 縮小最大字體為80
                     ).generate(comments)

plt.figure(figsize=[8, 4])
plt.imshow(wordcloud.recolor(color_func=image_colors), alpha=1)
plt.axis('off')
'''保存到本地'''
plt.savefig('圖14.jpg', dpi=600, bbox_inches='tight', quality=95)
plt.show()

  這時我們會發現詞雲圖上繪製出的全是亂碼,這是因為matplotlib默認字體是不包含中文的:


圖14 中文亂碼問題

  這時我們只需要為WordCloud傳入font_path參數即可,這裏我們選擇SimHei字體:

from PIL import Image
import numpy as np
from wordcloud import ImageColorGenerator

waimai_mask = np.array(Image.open('美團外賣logo蒙版.png'))
image_colors = ImageColorGenerator(waimai_mask)

'''從文本中生成詞雲圖'''
wordcloud = WordCloud(font_path='SimHei.ttf', # 定義SimHei字體文件
                      background_color='white', # 背景色為白色
                      height=400, # 高度設置為400
                      width=800, # 寬度設置為800
                      scale=20, # 長寬拉伸程度程度設置為20
                      prefer_horizontal=0.2, # 調整水平显示傾向程度為0.2
                      mask=waimai_mask, # 添加蒙版
                      max_words=1000, # 設置最大显示字數為1000
                      relative_scaling=0.3, # 設置字體大小與詞頻的關聯程度為0.3
                      max_font_size=80 # 縮小最大字體為80
                     ).generate(comments)

plt.figure(figsize=[8, 4])
plt.imshow(wordcloud.recolor(color_func=image_colors), alpha=1)
plt.axis('off')
'''保存到本地'''
plt.savefig('圖15.jpg', dpi=600, bbox_inches='tight', quality=95)
plt.show()

圖15

三、利用stylecloud繪製詞雲圖

  stylecloud是一個較為嶄新的模塊,它基於wordcloud,添加了一系列的嶄新特性譬如漸變顏色等,可以支持更為個性化的詞雲圖創作:


圖16 styleword製作詞雲圖示例

3.1 從一個簡單的例子開始

  這裏我們沿用上一章節中使用過的處理好的text來繪製詞雲圖:

import stylecloud
from IPython.display import Image # 用於在jupyter lab中显示本地圖片

'''生成詞雲圖'''
stylecloud.gen_stylecloud(text=text, 
                          size=512,
                          output_name='圖17.png')

'''显示本地圖片'''
Image(filename='圖17.png') 

圖17

  可以看出,styleword生成詞雲圖的方式跟wordcloud不同,它直接就將原始文本轉換成本地詞雲圖片文件,下面我們針對其繪製詞雲圖的細節內容進行介紹。

3.2 gen_stylecloud

  在stylecloud中繪製詞雲圖只需要gen_stylecloud這一個函數即可,其主要參數及說明如下:

text:字符串,格式同WordCloud中的generate()方法中傳入的text
gradient:控制詞雲圖顏色漸變的方向,’horizontal’表示水平方向上漸變,’vertical’表示豎直方向上漸變,默認為’horizontal’
size:控制輸出圖像文件的分辨率(因為stylecloud默認輸出方形圖片,所以size傳入的單個整數代表長和寬),默認為512
icon_name:這是stylecloud中的特殊參數,通過傳遞對應icon的名稱,你可以使用多達1544個免費圖標來作為詞雲圖的蒙版,點擊查看你可以免費使用的圖標蒙版樣式,默認為’fas fa-flag’
palette:控制調色方案,stylecloud的調色方案調用了,這是一個非常實用的模塊,其內部收集了數量驚人的大量的經典調色方案,默認為’cartocolors.qualitative.Bold_5′
background_color:字符串,控制詞雲圖底色,可傳入顏色名稱或16進制色彩,默認為’white’
max_font_size:同wordcloud
max_words:同wordcloud
stopwords:bool型,控制是否開啟去停用詞功能,默認為True,調用自帶的英文停用詞表
custom_stopwords:傳入自定義的停用詞List,配合stopwords共同使用
output_name:控制輸出詞雲圖文件的文件名,默認為stylecloud.png
font_path:傳入自定義字體*.ttf文件的路徑
random_state:同wordcloud

  對上述參數有所了解之後,下面我們在圖17的基礎上進行改良,首先我們將圖標形狀換成的樣子,接着將配色方案修改為:

'''生成詞雲圖'''
stylecloud.gen_stylecloud(text=text, 
                          size=1024,
                          output_name='圖18.png',
                          palette='scientific.diverging.Broc_3', # 設置配色方案
                          icon_name='fas fa-bomb' # 設置圖標樣式
                         )

'''显示本地圖片'''
Image(filename='圖18.png') 

圖18

3.3 繪製中文詞雲圖

  在wordcloud中繪製中文詞雲圖類似wordcloud只需要注意傳入支持中文的字體文件即可,下面我們使用一個微博語料數據weibo_senti_100k.csv來舉例:

weibo = pd.read_csv('weibo_senti_100k.csv')
weibo_text = [word for word in jieba.cut(' '.join(re.findall('[\u4e00-\u9fa5]+', ' '.join(weibo['review'].tolist())))) if word != ' ' and word not in stopwords]
weibo_text[:10]

圖19

  接着我們將蒙版圖標樣式換成,將色彩方案換成:

'''生成詞雲圖'''
stylecloud.gen_stylecloud(text=text, 
                          size=1024,
                          output_name='圖20.png',
                          palette='colorbrewer.sequential.Reds_3', # 設置配色方案為https://jiffyclub.github.io/palettable/colorbrewer/sequential/#reds_3
                          icon_name='fab fa-weibo', # 設置圖標樣式
                          gradient='horizontal', # 設置顏色漸變方向為水平
                          collocations=False # 不允許詞語重複显示
                         )

'''显示本地圖片'''
Image(filename='圖20.png') 

圖20

  以上就是本文的全部內容,如有筆誤望指出!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

印度研究:森林大火致黑碳更濃 加速冰河融化

摘錄自2020年2月4日中央通訊社報導

印度一項最新研究顯示,森林大火引發的黑碳(black carbon)濃度增加,加速冰河融化,更引發海平面升高及氣候變遷惡化。印度斯坦時報(Hindustan Times)今天(4日)引述WIHG科學家內基(PS Negi)指出,經過研究團隊過去幾年在北阿坎德省根戈催里冰河(Gangotri Glacier)鄰近地區的觀察與研究,森林大火導致黑碳濃度增加近一倍,加速了這條冰河的融化速度。

黑碳是一種懸浮粒子,源於石油、煤、木炭、樹木、柴草、塑膠垃圾、動物糞便等含碳物質燃燒不完全及氧化後所形成的產物。內基說,黑碳已公認是造成氣候變遷的第二重要人為因素。由於黑碳吸收更多光源且釋放紅外線輻射,從而提高當地溫度,導致冰河融化。當喜瑪拉雅山區高處的黑碳濃度增加時,使喜瑪拉雅山區的冰河融化更快。他認為,由於源自全球、區域和本地的開發及污染不斷累積,導致喜瑪拉雅山區的黑碳濃度增加,進而加速冰河融化,連帶影響全球氣候變遷。

至於森林大火的起因,根據印度森林調查報告(Forest Survey of India),北阿坎德省通常在2到6月通報森林火災,火災起因包括人為因素及閃電。根據官方統計,從2000年以來,北阿坎德省森林大火導致4萬4554公頃的森林遭到破壞。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

溫暖海水底下竄 格陵蘭冰川加快融化速度

摘錄自2020年2月4日中央通訊社報導

科學家早就知道氣溫上升會造成格陵蘭冰川表層融化,但最新研究發現,另一項威脅也從冰川下方展開:在格陵蘭巨大冰川底下流動的溫暖海水使融冰速度加快。

這項研究今天(3日)刊登在英國期刊「自然地球科學」(Nature Geoscience),參與調查的學者研究格陵蘭東北部一條被稱為「北緯79度冰川」的眾多「冰舌」 (ice tongue)之一。美國有線電視新聞網(CNN)報導,冰舌就是漂浮在水上卻沒跟陸地冰層脫離的冰條。這群科學家研究的這條巨大冰舌將近80公里長。這項新研究顯示,一股來自大西洋且超過1.6公里寬的溫暖海水,能直接流向這群學者研究的冰川,讓大量熱能接觸冰層,進而加速冰川融化。

格陵蘭大量融冰是現在全球海平面上升的最主要原因,那裡的融冰水量能讓全球海平面上升超過7.3公尺。丹麥氣象研究所氣候科學家莫特拉姆(Ruth Mottram)曾指出,光是去年7月,格陵蘭冰層就有1970億噸的冰消失,相當於8000萬個奧運泳池的水量。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

南投搬家前需注意的眉眉角角,別等搬了再說!

繼蘇門答臘之後 印尼峇里島也傳非洲豬瘟疫情

摘錄自2020年02月05日中央社報導

印尼有關單位今(5日)表示,峇里島數百隻豬因感染非洲豬瘟而死,這是印尼度假勝地峇里島首次爆發的疫情。此前印尼蘇門答臘則是有3萬隻豬因此遭殃。

峇里島農業暨糧食安全局局長維斯努阿德哈納(Ida Bagus Wisnuardhana)表示,自去年12月中旬至今,當地將近900隻豬因感染非洲豬瘟病死。

為了平息各方對疫情的憂慮,他說,過去一週豬隻接連死亡似乎已止住,並說峇里島將如期在7日舉辦「豬肉嘉年華」(Pork Festival)美食節活動。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

用吃的就解決! 外來種海膽破壞海藻林 新創公司投入壽司商機

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益