打造數(shù)據(jù)科學(xué)作品集:用數(shù)據(jù)講故事

作者:Vik Paruchuri
譯者:Nick Tang
校對(duì):EarlGrey
出品:PythonTG 翻譯組/編程派

這是「如何打造數(shù)據(jù)科學(xué)作品集」系列教程的第一篇。如果覺得不錯(cuò)溪烤,可以訂閱我們第一時(shí)間獲取最新更新特漩。這個(gè)系列的文章都很長(zhǎng)捻悯,建議先收藏再找時(shí)間詳細(xì)閱讀男旗。如果你覺得譯文讀起來不舒服球散,可以點(diǎn)此閱讀原文巨缘,并給我們提些改建建議添忘。

數(shù)據(jù)科學(xué)公司在招聘時(shí)越來越看重個(gè)人作品集,原因在于作品集是衡量實(shí)際能力最好的方式之一若锁。好消息是搁骑,你完全掌控著自己的作品集。如果付出一些努力又固,你就可以打造一套令用人單位印象深刻的高質(zhì)量作品集仲器。

想要打造高質(zhì)量作品集,第一步需要搞清楚應(yīng)該在作品中展現(xiàn)什么能力仰冠。公司希望數(shù)據(jù)科學(xué)家具備的能力(也就是他們希望作品集能夠展示的能力)包括:

  • 溝通能力
  • 與他人協(xié)作能力
  • 技術(shù)能力
  • 數(shù)據(jù)推斷能力
  • 主觀能動(dòng)性

一個(gè)好的作品集一般由多個(gè)項(xiàng)目構(gòu)成乏冀,每一個(gè)項(xiàng)目展示以上 1-2 個(gè)能力點(diǎn)。本文是教你怎樣打造一個(gè)全面的數(shù)據(jù)科學(xué)作品系列的第一篇洋只。我們將介紹怎樣打造作品集中的第一個(gè)項(xiàng)目辆沦,怎樣使用數(shù)據(jù)講述一個(gè)有效的故事。本篇結(jié)束時(shí)识虚,你將擁有一個(gè)展示溝通能力和數(shù)據(jù)推斷能力的數(shù)據(jù)科學(xué)項(xiàng)目肢扯。

用數(shù)據(jù)講故事

數(shù)據(jù)科學(xué)的本質(zhì)是溝通。你通過數(shù)據(jù)得到了一些洞察担锤,然后采用有效的方式將其傳播給他人蔚晨,并向其推銷你的解決方案「匮可見使用數(shù)據(jù)來講述一個(gè)有效的故事铭腕,是數(shù)據(jù)科學(xué)家最重要的技能之一。一個(gè)有效的故事可以使你的洞察更有說服力多糠,同時(shí)能幫助他人理解你的觀點(diǎn)累舷。

數(shù)據(jù)科學(xué)中的故事需要圍繞著你發(fā)現(xiàn)了什么,怎么發(fā)現(xiàn)的熬丧,意味著什么進(jìn)行講述笋粟。舉個(gè)例子,你發(fā)現(xiàn)公司利潤(rùn)去年下降了25%析蝴。僅僅闡述這個(gè)事實(shí)是不夠的害捕,你必須說明為什么利潤(rùn)會(huì)下降,可以通過什么方式來解決闷畸。

用數(shù)據(jù)講故事的要點(diǎn)如下:

  • 搞清楚并且設(shè)置故事的上下文
  • 從多個(gè)角度進(jìn)行探索
  • 有說服力的形象化展示
  • 使用多種數(shù)據(jù)源
  • 敘述的一致性

這里最有效的工具是 Jupyter notebook尝盼。如果你對(duì)此不是很熟悉,請(qǐng)參考這個(gè)教程佑菩。Jupyter notebook 允許你交互式的探索數(shù)據(jù)盾沫,支持將結(jié)果分享到多個(gè)網(wǎng)站裁赠,包括 Github 。通過分享赴精,他人可以很好的與你協(xié)作佩捞,并擴(kuò)充你的成果。

我們會(huì)在文中使用 Jupyter notebook 以及一些 Python 數(shù)據(jù)科學(xué)庫蕾哟,如 Pandas 和 matplotlib一忱。

選擇項(xiàng)目主題

創(chuàng)建項(xiàng)目的第一步是決定主題。你需要選擇感興趣且有動(dòng)力去研究的題目谭确。我們都知道為了做項(xiàng)目而做帘营,還是真的感興趣去做,這之間有巨大區(qū)別逐哈。因此這一步值得多花點(diǎn)功夫芬迄,確保能夠找到真正感興趣的東西。

尋找題目的一個(gè)好辦法是瀏覽不同的數(shù)據(jù)集昂秃,看看有什么有趣的東西禀梳。這里推薦一些好的站點(diǎn):

  • Data.gov – 包含政府信息。
  • /r/datasets – 一個(gè)reddit的子集擁有非常多的有趣數(shù)據(jù)集械蹋。
  • Awesome datasets – Github上的一些數(shù)據(jù)集出皇。
  • rs.io – 一個(gè)很棒的Blog,發(fā)布了很多有趣的數(shù)據(jù)哗戈。

一般現(xiàn)實(shí)中,你拿到的經(jīng)常不是一個(gè)完美的單個(gè)數(shù)據(jù)集荷科。通常需要聚合不同的數(shù)據(jù)源唯咬,或者做大量的數(shù)據(jù)清理工作。當(dāng)選題對(duì)你來說真的非常有意思畏浆,多花點(diǎn)時(shí)間去處理數(shù)據(jù)是非常值得的胆胰,同時(shí)在這個(gè)過程中你也可以炫耀一下技能。

本文我們使用紐約市公立學(xué)校的數(shù)據(jù)刻获,你可以在這里得到它們蜀涨。

選定題目

能夠從一而終的完成項(xiàng)目是非常重要的。因此蝎毡,限制項(xiàng)目的范圍非常關(guān)鍵厚柳,這可以讓我們清楚地知道我們可以完成它。

本文中沐兵,我們著眼于美國(guó)高中生的SAT 成績(jī)以及其他統(tǒng)計(jì)數(shù)據(jù)來做數(shù)據(jù)分析别垮。SAT(Scholastic Aptitude Test) 是美國(guó)高中生申請(qǐng)大學(xué)前參加的一項(xiàng)考試。大學(xué)在作出是否入取決定時(shí)會(huì)參考考試成績(jī)扎谎。這個(gè)考試分為三個(gè)部分碳想,每部分 800 分烧董,總分 2400 (雖然總分曾改來改去很多次,但在這個(gè)數(shù)據(jù)集里仍是2400)胧奔。各高中經(jīng)常以 SAT 的平均成績(jī)進(jìn)行排名逊移,SAT 成績(jī)高代表著這個(gè)學(xué)區(qū)的高品質(zhì)。

有人提出 SAT 對(duì)美國(guó)的某些種族人群不公平龙填,因此對(duì)紐約市的數(shù)據(jù)進(jìn)行分析可以幫組我們進(jìn)一步搞清楚 SAT 考試的公平性螟左。

從這里獲得SAT數(shù)據(jù)各高中數(shù)據(jù)。這將是項(xiàng)目的基礎(chǔ)觅够,但是我們還需要更多的信息來確保有說服力的分析胶背。

補(bǔ)充數(shù)據(jù)

一旦找到了好題目,接下來去多找一些有助于這個(gè)題目或者能使你更進(jìn)一步深入研究的數(shù)據(jù)集喘先。最好提前準(zhǔn)備钳吟,以便在開始建立項(xiàng)目前擁有盡可能多的數(shù)據(jù)。通常過少的數(shù)據(jù)意味著過早的放棄項(xiàng)目窘拯。

在這個(gè)項(xiàng)目里红且,某個(gè)網(wǎng)站上就有多個(gè)相關(guān)數(shù)據(jù)集,包括了生源統(tǒng)計(jì)信息以及測(cè)試分?jǐn)?shù)等涤姊。

這里是所有將使用數(shù)據(jù)集的鏈接:

所有的這些數(shù)據(jù)集是相互關(guān)聯(lián)的拖吼,我們可以在分析前先組合他們鳞上。

獲取背景信息

在深入分析數(shù)據(jù)之前,調(diào)查一些背景信息非常有用绿贞。本例中因块,我們已知一些非常有用的信息:

  • 紐約市有五個(gè)區(qū),各自是獨(dú)立的區(qū)域籍铁。
  • 所有學(xué)校分布在各個(gè)學(xué)區(qū)里涡上,每個(gè)區(qū)包含數(shù)十個(gè)學(xué)校趾断。
  • 數(shù)據(jù)集里的學(xué)校并非都是高中,因此我們需要做一些數(shù)據(jù)清理工作吩愧。
  • 每所有學(xué)校都有一個(gè)DBN (District Borough Number)唯一編號(hào)芋酌。
  • 通過聚合每個(gè)區(qū)的數(shù)據(jù),我們可以繪制出各個(gè)區(qū)域之間的差異雁佳。

理解數(shù)據(jù)

為了能夠真正理解這些數(shù)據(jù)的上下文脐帝,你要花點(diǎn)時(shí)間去探索數(shù)據(jù)。上面每個(gè)鏈接都有一些關(guān)于數(shù)據(jù)及相關(guān)列的描述糖权。我們手里有高中生的 SAT 成績(jī)堵腹,以及生源信息等其他數(shù)據(jù)集。

我們可以執(zhí)行代碼來讀取數(shù)據(jù)星澳。使用 Jupyter notebook 來探索這些數(shù)據(jù)疚顷,下面的代碼將:

  • 遍歷每個(gè)下載的數(shù)據(jù)文件
  • 把文件數(shù)據(jù)讀入到Pandas DataFrame
  • 將 DataFrame 統(tǒng)一放入一個(gè)Python字典
import pandas
import numpy as np

files = ["ap_2010.csv", "class_size.csv", "demographics.csv", "graduation.csv", "hs_directory.csv", "math_test_results.csv", "sat_results.csv"]

data = {}
for f in files:
    d = pandas.read_csv("schools/{0}".format(f))
    data[f.replace(".csv", "")] = d

數(shù)據(jù)讀入后,我們可以在 DataFrames 上使用 head 方法打印前 5 行數(shù)據(jù):

for k,v in data.items():
    print("\n" + k + "\n")
    print(v.head())
DataFrames

可以發(fā)現(xiàn)數(shù)據(jù)集中的一些明顯特征:

  • 大多數(shù)數(shù)據(jù)集包含 DBN 列禁偎。
  • 一些字段對(duì)繪圖有用腿堤,特別是 Location 1,其中包含了坐標(biāo)信息如暖。
  • 一些數(shù)據(jù)集似乎包含一個(gè)學(xué)校的多條信息(重復(fù)的 DBN )笆檀,這意味著我們必須做一些預(yù)處理。

統(tǒng)一數(shù)據(jù)

為了更容易的處理數(shù)據(jù)盒至,我們需要將所有的單個(gè)數(shù)據(jù)集集中到一個(gè)數(shù)據(jù)集里酗洒。這樣可以讓我們更快的比較數(shù)據(jù)集之間的列。為了做到這一點(diǎn)妄迁,第一步我們需要找到一個(gè)統(tǒng)一的公共列寝蹈。從上面的輸出結(jié)果來看,你會(huì)發(fā)現(xiàn) DBN 出現(xiàn)在大多數(shù)的數(shù)據(jù)集里登淘,看起來可以用作公共列。

如果我們谷歌一下 DBN New York City Schools封字,會(huì)找到這個(gè)頁面黔州,解釋了 DBN 是每一個(gè)學(xué)校的唯一編號(hào)。當(dāng)我們探索數(shù)據(jù)集阔籽,特別是政府?dāng)?shù)據(jù)集時(shí)流妻,為了搞清楚每一個(gè)列的意思,做一些調(diào)查工作是必不可少的笆制。

現(xiàn)在有個(gè)問題绅这,class_sizehs_directory 數(shù)據(jù)集沒有發(fā)現(xiàn) DBN 字段。hs_directory 數(shù)據(jù)集只有 dbn 字段在辆,我們可以通過重命名這個(gè)列或者把它拷貝到一個(gè)DBN 的新列來解決证薇。而對(duì) class_size 數(shù)據(jù)集度苔,我們需要采用其他辦法來處理。

DBN 列看起來像這樣:

data["demographics"]["DBN"].head()
0    01M015
1    01M015
2    01M015
3    01M015
4    01M015
Name: DBN, dtype: object

我們?cè)倏匆谎?class_size 的前 5 行數(shù)據(jù):

data["class_size"].head()
數(shù)據(jù)科學(xué)

如上圖所見浑度,看起來 DBN 實(shí)際上是由CSD寇窑、 BOROUGHSCHOOL CODE 組合而成。DBN 全稱為 District Borough Number 箩张。csd 字段表示 District甩骏,BOROUGH 字段表示 borough,再與 SCHOOL CODE 字段一起最終組成DBN先慷。

想洞察數(shù)據(jù)之間的這種關(guān)系并沒有什么系統(tǒng)化的方法饮笛,只能經(jīng)過探索和嘗試來找到答案。

現(xiàn)在我們知道怎樣構(gòu)建 DBN 了论熙,可以把它添加到 class_sizehs_directory 數(shù)據(jù)集里:

data["class_size"]["DBN"] = data["class_size"].apply(lambda x: "{0:02d}{1}".format(x["CSD"], x["SCHOOL CODE"]), axis=1)
data["hs_directory"]["DBN"] = data["hs_directory"]["dbn"]

添加調(diào)查數(shù)據(jù)

最有趣的數(shù)據(jù)集之一福青,應(yīng)該是學(xué)生、父母赴肚、老師的問卷調(diào)查數(shù)據(jù)素跺,囊括了對(duì)每個(gè)學(xué)校的安全程度、學(xué)術(shù)水平等等反饋數(shù)據(jù)誉券。在組合數(shù)據(jù)集之前指厌,讓我們添加這些調(diào)查數(shù)據(jù)。現(xiàn)實(shí)工作中踊跟,分析數(shù)據(jù)的途中你經(jīng)常會(huì)碰到你想要加入的有趣數(shù)據(jù)踩验。使用Jupyter notebook 這樣靈活的工具,可以讓你快速添加額外代碼商玫,并且重新運(yùn)行你的分析箕憾。

我們將要添加調(diào)查數(shù)據(jù)到我們的 data 字典里,然后再組合所有的數(shù)據(jù)集拳昌。調(diào)查數(shù)據(jù)包含兩個(gè)文件袭异,一個(gè)針對(duì)所有學(xué)習(xí),一個(gè)是針對(duì) 75 區(qū)的學(xué)校炬藤。我們需要寫一些代碼來組合御铃。在下面的代碼中,我們將

  • 使用 windows-1252 編碼讀入所有學(xué)校的數(shù)據(jù)沈矿。
  • 使用 windows-1252 編碼讀入 75 區(qū)學(xué)校的數(shù)據(jù)上真。
  • 添加一個(gè) flag 來數(shù)據(jù)來自哪個(gè)區(qū)。
  • 使用 DataFrames 的 concat 方法來合并以上數(shù)據(jù)羹膳。
survey1 = pandas.read_csv("schools/survey_all.txt", delimiter="\t", encoding='windows-1252')
survey2 = pandas.read_csv("schools/survey_d75.txt", delimiter="\t", encoding='windows-1252')
survey1["d75"] = False
survey2["d75"] = True
survey = pandas.concat([survey1, survey2], axis=0)

一旦我們完成調(diào)查數(shù)據(jù)的合并睡互,還有一個(gè)復(fù)雜的事情要處理。為了方便進(jìn)行比較和找出列直接關(guān)聯(lián),我們需要減少數(shù)據(jù)集中的列數(shù)就珠。不幸的是寇壳,調(diào)查數(shù)據(jù)里包含太多對(duì)我們沒有用的列:

survey.head()
數(shù)據(jù)的合并

我們可以通過查看與調(diào)查數(shù)據(jù)一起下載下來的數(shù)據(jù)字典文件,來找出我們需要的重要字段去簡(jiǎn)化列:

需要的重要字段去簡(jiǎn)化列

這樣我們就可以刪除 survey 中多余的列:

survey["DBN"] = survey["dbn"]
survey_fields = ["DBN", "rr_s", "rr_t", "rr_p", "N_s", "N_t", "N_p", "saf_p_11", "com_p_11", "eng_p_11", "aca_p_11", "saf_t_11", "com_t_11", "eng_t_10", "aca_t_11", "saf_s_11", "com_s_11", "eng_s_11", "aca_s_11", "saf_tot_11", "com_tot_11", "eng_tot_11", "aca_tot_11",]
survey = survey.loc[:,survey_fields]
data["survey"] = survey
survey.shape
(1702, 23)

確保你能夠理解每個(gè)數(shù)據(jù)集包含什么嗓违,相關(guān)列是什么九巡,可以為日后分析節(jié)省很多的時(shí)間和精力。

壓縮數(shù)據(jù)集

再次看一下數(shù)據(jù)集蹂季,我們馬上發(fā)現(xiàn)一個(gè)新的問題:

data["class_size"].head()
壓縮數(shù)據(jù)集

class_size 中對(duì)應(yīng)一個(gè)高中存在多行數(shù)據(jù)(及重復(fù)的 DBNSCHOOL NAME )冕广。然而 sat_results 里每個(gè)高中只有一條數(shù)據(jù):

data["sat_results"].head()
壓縮數(shù)據(jù)集

為了能夠聯(lián)合數(shù)據(jù)集,我們需要找到一種方式來保證一個(gè)高中對(duì)應(yīng)一行數(shù)據(jù)偿洁。如果不這樣做撒汉,我們將無法比較 SAT 成績(jī)與班級(jí)大小。首先我們需要更好地理解數(shù)據(jù)涕滋,然后做一些聚合睬辐。在 class_size 數(shù)據(jù)集里,GRADEPROGRAM TYPE 字段對(duì)于一個(gè)學(xué)校存在多個(gè)值宾肺。通過限制一個(gè)字段只有一個(gè)值溯饵,我們可以過濾掉大部分的重復(fù)行。在下面的代碼中锨用,我們將:

  • 僅僅保留 class_sizeGRADE 字段是 09-12 的值丰刊。
  • 僅僅保留 class_sizePROGRAM TYPEGEN ED 的值。
  • DBN 進(jìn)行g(shù)roup增拥,計(jì)算每個(gè)列的平均值啄巧,得到每所學(xué)校平均的 class_size 值。
  • 重置索引掌栅,將 DBN 作為列重新加回秩仆。
class_size = data["class_size"]
class_size = class_size[class_size["GRADE "] == "09-12"]
class_size = class_size[class_size["PROGRAM TYPE"] == "GEN ED"]
class_size = class_size.groupby("DBN").agg(np.mean)
class_size.reset_index(inplace=True)
data["class_size"] = class_size

壓縮其他數(shù)據(jù)集

同樣,我們需要壓縮 demographics 數(shù)據(jù)集猾封。這個(gè)數(shù)據(jù)集收集了同一個(gè)學(xué)校多年的數(shù)據(jù)澄耍,因此存在重復(fù)數(shù)據(jù)。我們將僅僅挑選出 schoolyear 字段里為最近年份的晌缘,來去除重復(fù)的數(shù)據(jù):

demographics = data["demographics"]
demographics = demographics[demographics["schoolyear"] == 20112012]
data["demographics"] = demographics

還需要壓縮 math_test_results 數(shù)據(jù)集逾苫。這個(gè)數(shù)據(jù)集按 GradeYear 進(jìn)行分割。我們可以只保留某一年中某個(gè)年級(jí)的數(shù)據(jù):

data["math_test_results"] = data["math_test_results"][data["math_test_results"]["Year"] == 2011]
data["math_test_results"] = data["math_test_results"][data["math_test_results"]["Grade"] == '8']

最后枚钓,壓縮 graduation 數(shù)據(jù)集:

data["graduation"] = data["graduation"][data["graduation"]["Cohort"] == "2006"]
data["graduation"] = data["graduation"][data["graduation"]["Demographic"] == "Total Cohort"]

在真正開始項(xiàng)目工作之前,數(shù)據(jù)的清理和探索是至關(guān)重要瑟押。擁有一個(gè)良好的搀捷、一致的數(shù)據(jù)集會(huì)大大加快后續(xù)分析工作。

計(jì)算變量值

計(jì)算變量值對(duì)加快分析過程有兩個(gè)好處,讓日后進(jìn)行比較更快嫩舟,能夠比較原本不能比較的字段氢烘。目前我們要做的第一件事情是從 SAT Math Avg. ScoreSAT Critical Reading Avg. Score家厌、and SAT Writing Avg. Score 列來計(jì)算 SAT 總分播玖。下面的代碼:

  • 把每個(gè) SAT 成績(jī)中的列從字符串轉(zhuǎn)為數(shù)字。
  • 合計(jì)所有列到 sat_score 列饭于,代表 SAT 總分蜀踏。
cols = ['SAT Math Avg. Score', 'SAT Critical Reading Avg. Score', 'SAT Writing Avg. Score']
for c in cols:
    data["sat_results"][c] = pandas.to_numeric(data["sat_results"][c], errors='coerce')

data['sat_results']['sat_score'] = data['sat_results'][cols[0]] + data['sat_results'][cols[1]] + data['sat_results'][cols[2]]

接下里,我們來解析每個(gè)學(xué)校的坐標(biāo)位置掰吕,這個(gè)可以讓我們繪制每所學(xué)校的位置果覆。下面的代碼:

  • Location 1 列解析出經(jīng)緯度。
  • 轉(zhuǎn)換經(jīng)緯度為數(shù)字殖熟。
data["hs_directory"]['lat'] = data["hs_directory"]['Location 1'].apply(lambda x: x.split("\n")[-1].replace("(", "").replace(")", "").split(", ")[0])
data["hs_directory"]['lon'] = data["hs_directory"]['Location 1'].apply(lambda x: x.split("\n")[-1].replace("(", "").replace(")", "").split(", ")[1])

for c in ['lat', 'lon']:
    data["hs_directory"][c] = pandas.to_numeric(data["hs_directory"][c], errors='coerce')

現(xiàn)在局待,我們可以重新打印每一個(gè)數(shù)據(jù)集來看看:

for k,v in data.items():
    print(k)
    print(v.head())
打印每一個(gè)數(shù)據(jù)集

合并數(shù)據(jù)集

現(xiàn)在我們完成了所有的準(zhǔn)備工作,可以使用 DBN 列來將數(shù)據(jù)集合并在一起了菱属。合并后我們將獲得一個(gè)有著數(shù)百個(gè)列的數(shù)據(jù)集钳榨。合并時(shí)注意一些數(shù)據(jù)集存在缺失部分高中的數(shù)據(jù)。為了不丟失這部分?jǐn)?shù)據(jù)纽门,我們需要使用 outer join 來合并數(shù)據(jù)集薛耻。在現(xiàn)實(shí)世界里,數(shù)據(jù)缺失是很常見的膜毁。有能力推理和處理缺失數(shù)據(jù)是作品集中重要的展示部分昭卓。

你可以從這里了解不同類型的 join 。

下面的代碼中瘟滨,我們將:

  • 遍歷 data 字典里的每一項(xiàng)候醒。
  • 打印非唯一 DBN 的數(shù)量。
  • 決定 join 的策略杂瘸,inner 還是 outer倒淫。
  • DBN 來 join 所有的數(shù)據(jù)集,存于 DataFrame full败玉。
flat_data_names = [k for k,v in data.items()]
flat_data = [data[k] for k in flat_data_names]
full = flat_data[0]
for i, f in enumerate(flat_data[1:]):
    name = flat_data_names[i+1]
    print(name)
    print(len(f["DBN"]) - len(f["DBN"].unique()))
    join_type = "inner"
    if name in ["sat_results", "ap_2010", "graduation"]:
        join_type = "outer"
    if name not in ["math_test_results"]:
        full = full.merge(f, on="DBN", how=join_type)

full.shape
sat_results
0
demographics
0
graduation
0
hs_directory
0
ap_2010
1
survey
0
class_size
0


(396, 174)

添加值

現(xiàn)在我們有了 DataFrame full敌土, 幾乎包含所有我們需要信息的。但是运翼,仍然有部分字段的數(shù)據(jù)是缺失的返干。例如我們想將 AP 考試的結(jié)果與 SAT 成績(jī)關(guān)聯(lián)到一起的話,我們需要將列轉(zhuǎn)化為數(shù)字血淌,然后填入所有缺失的數(shù)值:

cols = ['AP Test Takers ', 'Total Exams Taken', 'Number of Exams with scores 3 4 or 5']

for col in cols:
    full[col] = pandas.to_numeric(full[col], errors='coerce')

full[cols] = full[cols].fillna(value=0)

接著矩欠,我們計(jì)算 school_dist 列财剖,得到學(xué)校的區(qū)號(hào)。之后我們將使用這個(gè)數(shù)據(jù)按區(qū)去匹配學(xué)區(qū)癌淮,繪制學(xué)校的的統(tǒng)計(jì)數(shù)據(jù)躺坟。

full["school_dist"] = full["DBN"].apply(lambda x: x[:2])

最后我們用所有列的平均值,來填寫 full 中其他的缺失值:

full = full.fillna(full.mean())

計(jì)算關(guān)聯(lián)性

計(jì)算列之間的關(guān)聯(lián)性乳蓄,是探索數(shù)據(jù)集和檢查列相關(guān)度的好方法咪橙。這個(gè)方法可以告訴你哪個(gè)列與你感興趣的列有緊密關(guān)系。我們可以使用 Pandas DataFrames 提供的 corr 方法來計(jì)算得分虚倒。得分越接近 0美侦,表示越?jīng)]有相關(guān)性。越接近 1裹刮,則正相關(guān)性越強(qiáng)音榜,越接近 -1,則負(fù)相關(guān)性越強(qiáng):

full.corr()['sat_score']
計(jì)算關(guān)聯(lián)性

從上面的數(shù)據(jù)我們洞察到一些需要進(jìn)一步研究的東西:

  • 總錄取人數(shù)與 sat_score 有很強(qiáng)的相關(guān)性捧弃。這有點(diǎn)令我們驚訝赠叼,在我們的認(rèn)知中,越小的學(xué)校违霞,應(yīng)該越注重于學(xué)生教育嘴办,分?jǐn)?shù)應(yīng)該更高才對(duì)。
  • 女性百分比(female_per)與 SAT 成績(jī)成正比买鸽,男性比例(male_per) 則相反涧郊。
  • 調(diào)查反饋數(shù)據(jù)與 SAT 成績(jī)沒有什么相關(guān)性。
  • SAT 成績(jī)中有顯著的種族不平等性(white_per, asian_per, black_per, hispanic_per)眼五。
  • ell_percent 與 SAT 成績(jī)有強(qiáng)烈的負(fù)相關(guān)性妆艘。

以上每一項(xiàng)都是一個(gè)潛在的探索方向,都可以使用數(shù)據(jù)來敘述一個(gè)故事看幼。

設(shè)定上下文

在我們深入數(shù)據(jù)之前批旺,要為自己以及讀者設(shè)定一個(gè)上下文。使用可探索的圖表或者地圖是一個(gè)好的方式诵姜。在本例中汽煮,我們按學(xué)校位置繪制出地圖,這可以幫組我們理解即將探索的問題棚唆。

下面的代碼:

  • 設(shè)立地圖中心為紐約市
  • 為每所學(xué)校添加一個(gè)標(biāo)記
  • 顯示地圖
import folium
from folium import plugins

schools_map = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10)
marker_cluster = folium.MarkerCluster().add_to(schools_map)
for name, row in full.iterrows():
    folium.Marker([row["lat"], row["lon"]], popup="{0}: {1}".format(row["DBN"], row["school_name"])).add_to(marker_cluster)
schools_map.save('schools.html')
schools_map
顯示地圖

這幅地圖很有幫助暇赤,但很難看出哪個(gè)地區(qū)的學(xué)校最多。因此宵凌,我們制作一副熱力圖:

schools_heatmap = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10)
schools_heatmap.add_children(plugins.HeatMap([[row["lat"], row["lon"]] for name, row in full.iterrows()]))
schools_heatmap.save("heatmap.html")
schools_heatmap
熱力圖

學(xué)區(qū)地圖繪制

熱力圖對(duì)于繪制梯度差異很方便鞋囊,但是我們希望使用更加結(jié)構(gòu)化的方式,來繪制城市中不同學(xué)校 SAT 成績(jī)的區(qū)別瞎惫。學(xué)區(qū)是一個(gè)很好的可視化選擇失暴,因?yàn)槊總€(gè)學(xué)期的管理各異坯门。紐約市有數(shù)十個(gè)學(xué)期,每個(gè)學(xué)區(qū)就是一個(gè)小的地理范圍逗扒。

我們可以根據(jù)學(xué)期計(jì)算 SAT 成績(jī),然后將其繪制到地圖上欠橘。在下面的代碼中矩肩,我們將:

  • 根據(jù)學(xué)區(qū)對(duì) full 進(jìn)行分組
  • 計(jì)算每個(gè)學(xué)區(qū)的行均值
  • 刪除 school_dist 字段中的前導(dǎo) 0 ,方便與地理區(qū)域數(shù)據(jù)進(jìn)行匹配
district_data = full.groupby("school_dist").agg(np.mean)
district_data.reset_index(inplace=True)
district_data["school_dist"] = district_data["school_dist"].apply(lambda x: str(int(x)))

現(xiàn)在我們可以繪制每個(gè)學(xué)區(qū)的平均 SAT 成績(jī)了肃续。為此黍檩,我們讀取 GeoJSON 格式的數(shù)據(jù),獲取每個(gè)學(xué)區(qū)的形狀始锚,然后通過 school_dist 列將 SAT 成績(jī)與學(xué)區(qū)形狀關(guān)聯(lián)在一起刽酱,最后繪制出想要的圖形:

def show_district_map(col):
    geo_path = 'schools/districts.geojson'
    districts = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10)
    districts.geo_json(
        geo_path=geo_path,
        data=district_data,
        columns=['school_dist', col],
        key_on='feature.properties.school_dist',
        fill_color='YlGn',
        fill_opacity=0.7,
        line_opacity=0.2,
    )
    districts.save("districts.html")
    return districts

show_district_map("sat_score")
學(xué)區(qū)地圖繪制

入學(xué)率與 SAT 成績(jī)

繪制完每個(gè)學(xué)員的位置,并按學(xué)區(qū)繪制出 SAT 成績(jī)之后瞧捌,我們就設(shè)定了分析的上下文棵里。閱讀我們分析報(bào)告的人將能更好地理解數(shù)據(jù)集背后的上下文。接來下姐呐,我們進(jìn)行此前提到的分析殿怜。第一個(gè)是學(xué)校的學(xué)生數(shù)量與 SAT 成績(jī)之間的關(guān)系。

可以使用散點(diǎn)圖曙砂,來比較學(xué)校的入學(xué)率和 SAT 成績(jī)头谜。

%matplotlib inline

full.plot.scatter(x='total_enrollment', y='sat_score')
入學(xué)率與 SAT 成績(jī)

我們發(fā)現(xiàn),左下方有大量的數(shù)據(jù)點(diǎn)聚集鸠澈,表示低入學(xué)率低 SAT 成績(jī)柱告。除此之外,SAT 成績(jī)和總?cè)雽W(xué)率之間似乎只有一點(diǎn)正相關(guān)笑陈。將相關(guān)性繪制出來可以發(fā)現(xiàn)意想不到的規(guī)律际度。

我們可以獲取低入學(xué)率、低 SAT 成績(jī)的學(xué)校名稱新锈,進(jìn)行進(jìn)一步的探索甲脏。

full[(full["total_enrollment"] < 1000) & (full["sat_score"] < 1000)]["School Name"]
入學(xué)率與 SAT 成績(jī)

谷歌搜索結(jié)果顯示,這些學(xué)校中大多數(shù)是針對(duì)正在學(xué)習(xí)英語的學(xué)生妹笆,因此入學(xué)率也低块请。這一結(jié)果告訴我們,并不是說總?cè)雽W(xué)率與 SAT 成績(jī)相關(guān)拳缠,而是學(xué)校中的學(xué)生是否以英語為第二外語墩新。

英語學(xué)生與 SAT 成績(jī)

既然我們知道了一個(gè)學(xué)習(xí)中英語學(xué)生的比例與較低的 SAT 成績(jī)相關(guān),可以進(jìn)一步作探索窟坐。ell_percent 列是每個(gè)學(xué)校中英語學(xué)生的比例海渊。我們繪制一副散點(diǎn)圖來分析二者之間的關(guān)系绵疲。

full.plot.scatter(x='ell_percent', y='sat_score')
英語學(xué)生與 SAT 成績(jī)

看上去有一些學(xué)校的英語學(xué)生比例很高,同時(shí)平均 SAT 成績(jī)卻很低臣疑。我們可以從學(xué)區(qū)層面對(duì)此進(jìn)行調(diào)查盔憨,弄清每個(gè)學(xué)區(qū)中英語學(xué)生的比例,然后檢查是否與根據(jù)學(xué)區(qū)繪制的 SAT 成績(jī)圖相匹配讯沈。

show_district_map("ell_percent")
根據(jù)學(xué)區(qū)繪制的 SAT 成績(jī)圖

從中可以看出郁岩,英語學(xué)生比例低的學(xué)區(qū),SAT 成績(jī)一般比較高缺狠,反之亦然问慎。

調(diào)查分?jǐn)?shù)與 SAT 成績(jī)

我們可以合理地假設(shè),學(xué)生挤茄、家長(zhǎng)和老師調(diào)查的結(jié)果與 SAT 成績(jī)與較大的相關(guān)性如叼。成績(jī)預(yù)期高的學(xué)校一般 SAT 成績(jī)也高。為了驗(yàn)證該假設(shè)穷劈,我們結(jié)合 SAT 成績(jī)和各種調(diào)查結(jié)果進(jìn)行繪圖:

full.corr()["sat_score"][["rr_s", "rr_t", "rr_p", "N_s", "N_t", "N_p", "saf_tot_11", "com_tot_11", "aca_tot_11", "eng_tot_11"]].plot.bar()
調(diào)查分?jǐn)?shù)與 SAT 成績(jī)

令人意外的是笼恰,相關(guān)性最高的兩個(gè)因素是 N_pN_s,即參與調(diào)查的家長(zhǎng)和學(xué)生的數(shù)量囚衔。二者與總?cè)雽W(xué)率之間均呈強(qiáng)相關(guān)性挖腰,因此可能會(huì)受到 ell_learners 的影響。相關(guān)性強(qiáng)的其他指標(biāo)是 saf_t_11 练湿。這是學(xué)生猴仑、家長(zhǎng)和老師對(duì)學(xué)校安全性的評(píng)價(jià)。一所學(xué)校越安全肥哎,學(xué)生更容易安心在其中學(xué)習(xí)辽俗。但是溝通、成績(jī)預(yù)期等其他因素與 SAT 成績(jī)之間沒有任何相關(guān)性篡诽。這或許說明紐約市在調(diào)查時(shí)的問題設(shè)計(jì)不妥崖飘,或者是調(diào)查因子就不正確(如果他們的目標(biāo)是提高 SAT 成績(jī)的話)。

種族和 SAT 成績(jī)

還有一個(gè)分析角度杈女,就是種族和 SAT 成績(jī)朱浴。二者之間有很大的相關(guān)性,可視化后將有助于理解背后的原因:

full.corr()["sat_score"][["white_per", "asian_per", "black_per", "hispanic_per"]].plot.bar()
種族和 SAT 成績(jī)

結(jié)果顯示达椰,白人和亞洲學(xué)生的比例越高翰蠢,SAT 成績(jī)就越高,而黑人和拉美裔學(xué)生比例越高啰劲,SAT 成績(jī)就越低梁沧。對(duì)于拉美裔學(xué)生來說,原因可能是近來移民的數(shù)量較大,其中多為英語學(xué)生愕把。我們可以按地區(qū)繪制拉美裔的比例,來驗(yàn)證相關(guān)性永高。

show_district_map("hispanic_per")
種族和 SAT 成績(jī)

拉美裔比例似乎和英語學(xué)生比例之間有一定相關(guān)性恋拍,但是要確定的話則需要做深入的分析和研究垛孔。

性別差別與 SAT 成績(jī)

最后一個(gè)分析角度是性別與SAT 成績(jī)。我們注意到女性比例更高的學(xué)校有更高的 SAT 成績(jī)芝囤。我們可以用一個(gè)柱狀圖來呈現(xiàn):

full.corr()["sat_score"][["male_per", "female_per"]].plot.bar()
性別差別與 SAT 成績(jī)

為了挖掘更多信息似炎,我們以 female_persat_score 列為軸繪制散點(diǎn)圖:

full.plot.scatter(x='female_per', y='sat_score')
性別差別與 SAT 成績(jī)

在圖中,我們發(fā)現(xiàn)了一些擁有高比例女性和高 SAT 分?jǐn)?shù)的學(xué)校悯姊。可以這樣獲取這些學(xué)校的名字:

full[(full["female_per"] > 65) & (full["sat_score"] > 1400)]["School Name"]
性別差別與 SAT 成績(jī)

谷歌搜索顯示贩毕,這些學(xué)校屬于表演藝術(shù)的精英學(xué)校悯许。所以可以同時(shí)解釋這些學(xué)校有較高的女性占比以及較高的 SAT 分?jǐn)?shù)。

AP 成績(jī)

目前為止辉阶,我們已經(jīng)考慮了生源方面的分析角度先壕。另一個(gè)方向是研究學(xué)生參加 AP 考試與SAT 成績(jī)的關(guān)系。二者之間應(yīng)該是相關(guān)的谆甜,學(xué)習(xí)成績(jī)好的學(xué)生垃僚,SAT 成績(jī)也應(yīng)更高。

full["ap_avg"] = full["AP Test Takers "] / full["total_enrollment"]

full.plot.scatter(x='ap_avg', y='sat_score')
AP 成績(jī)

看起來二者之間確實(shí)是正相關(guān)规辱。右上方的學(xué)校很有趣谆棺,他們的 SAT 成績(jī)很高,學(xué)生參加 AP 考試的比例也很高罕袋。

full[(full["ap_avg"] > .3) & (full["sat_score"] > 1700)]["School Name"]
AP 成績(jī)

谷歌搜索顯示改淑,它們大多數(shù)屬于需要考試才能入學(xué)的名牌學(xué)校。所以這些學(xué)校有高的 AP 考試比例也是理所當(dāng)然的浴讯。

故事總結(jié)

數(shù)據(jù)科學(xué)的世界里朵夏,故事絕不會(huì)完全結(jié)束。把你的分析分享給其他人榆纽,別人可以就任何感興趣的方向進(jìn)一步擴(kuò)充和塑造你的分析仰猖。比如本文中就有很多你可以繼續(xù)進(jìn)行挖掘的方向。

入門用數(shù)據(jù)來講故事最好的方式奈籽,就是嘗試擴(kuò)充或者復(fù)制其他人的分析饥侵。如果你決定這么做,非常歡迎你擴(kuò)展本文的分析唠摹,來看看你還會(huì)有什么發(fā)現(xiàn)爆捞。如果你這么做了,請(qǐng)?jiān)谙旅媪粞浴?/p>

下一步

如果你已經(jīng)學(xué)到這里了勾拉,代表你已經(jīng)理解如何用數(shù)據(jù)講故事和怎樣打造你的數(shù)據(jù)科學(xué)作品集煮甥。一旦你完成了你的數(shù)據(jù)科學(xué)項(xiàng)目盗温,請(qǐng)將它傳到 Github,這樣別人就可以與你協(xié)作了成肘。

本文首發(fā)于編程派公眾號(hào)及網(wǎng)站卖局。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市双霍,隨后出現(xiàn)的幾起案子砚偶,更是在濱河造成了極大的恐慌,老刑警劉巖洒闸,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件染坯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡丘逸,警方通過查閱死者的電腦和手機(jī)单鹿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來深纲,“玉大人仲锄,你說我怎么就攤上這事∨热担” “怎么了儒喊?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)币呵。 經(jīng)常有香客問我怀愧,道長(zhǎng),這世上最難降的妖魔是什么富雅? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任掸驱,我火速辦了婚禮,結(jié)果婚禮上没佑,老公的妹妹穿的比我還像新娘毕贼。我一直安慰自己,他們只是感情好蛤奢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布鬼癣。 她就那樣靜靜地躺著,像睡著了一般啤贩。 火紅的嫁衣襯著肌膚如雪待秃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天痹屹,我揣著相機(jī)與錄音章郁,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛暖庄,可吹牛的內(nèi)容都是我干的聊替。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼培廓,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼惹悄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肩钠,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤泣港,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后价匠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體当纱,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年踩窖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惫东。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡毙石,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出颓遏,到底是詐尸還是另有隱情徐矩,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布叁幢,位于F島的核電站滤灯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏曼玩。R本人自食惡果不足惜鳞骤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黍判。 院中可真熱鬧豫尽,春花似錦、人聲如沸顷帖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贬墩。三九已至榴嗅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間陶舞,已是汗流浹背嗽测。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肿孵,地道東北人唠粥。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓疏魏,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親厅贪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蠢护,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 「這個(gè)利器好酷啊」 AR Measure - 把你的手機(jī)變成一個(gè)具有AR力量的標(biāo)尺 Responder - 顯示網(wǎng)...
    知加閱讀 391評(píng)論 0 0
  • 恩格斯曾經(jīng)說過葵硕,先是語言,然后是語言和勞動(dòng)一起贯吓,使猿的腦髓形成了人的腦髓懈凹。強(qiáng)調(diào)了語言在人類歷史的偉大地位。 那語言...
    西西里牧羊人閱讀 766評(píng)論 0 0
  • 肖靈看著眼前這座低矮的土坯房悄谐,沐浴在午后的斜陽里介评,墻一側(cè)的爬墻虎,反射著夕陽的微光爬舰,越發(fā)的綠了们陆。 土房的大門敞開著...
    周小君0211閱讀 194評(píng)論 2 2
  • 今年我二十,對(duì)象比我小兩歲他還在上高中今年快高三情屹,談了半年多了坪仇,之前他很包容我各種小脾氣什么的,可是半年以后開始挑...
    一路上有你真好閱讀 358評(píng)論 0 0
  • 當(dāng)我已經(jīng)不再校園這個(gè)襁褓里垃你,已經(jīng)長(zhǎng)大遠(yuǎn)去椅文,踏出校園的大門,走向社會(huì)惜颇,朝著夢(mèng)奔跑皆刺。 已經(jīng)不在坐教室,認(rèn)真的看向黑板凌摄;...
    Witches小呆閱讀 226評(píng)論 0 0