記得有一個笑話:數據分析師的80%的時間,都消耗在數據清理上。很多時候數據處理不僅僅是效率的問題,有時候甚至沒辦法進行數據分析的操作。
為了加快數據清理的效率,同時為以後的建模和數據可視化做準備,R語言的Tidyverse包可以提供非常優秀的數據清理、整合和可視化的「一站式服務」。
本文將簡單介紹 Tidy 數據的思想以及舉例說明使用方法,本文所有的內容均為可重現研究(Reproducible research), 請點擊 閱讀原文 獲取相關數據及代碼。
Tidy 數據簡介 (Tidy data)為了更好的分析數據,我們需要將數據整合成Tidy格式 (Fig. 1)。Tidy 格式主要思想是儘量減少不同觀測值之間的耦合,以保證:
[Tidy 數據介紹及圖片引自 R for Data Science by Hadley Wickham]
Tidy 數據也有自己的額外開銷(overhead), 例如數據表中可能存在一些重複的數值,浪費了存儲空間;不利於矩陣運算來加速計算效率。鑑於現在的電腦技術發展非常迅速,即使存在一些電腦資源的浪費,Tidy 數據對用戶更加友好,這些額外開銷是可以接受的。
安裝Tidy首先安裝Tidyverse, 代碼如下所示。其實Tidyverse是一系列優秀軟體庫的合集,其中最常用的幾個package包括 dplyr,ggplot2 和 readr 等。
if (!require(tidyverse)){
install.packages("tidyverse")
}
本文的數據來源是美國USGS發布的施肥量分析,由於這些數據是通過地理信息系統(GIS)生成的,不太符合Tidy數據的思想, 筆者簡單介紹數據清理的過程。首先讀入數據, 原始數據有2M左右,包含110列和3,111行。
# read in data.
require(tidyverse)
# county level data of fertilizer application.
raw_data = read_csv("../data/CNTY_FERT_1987-2012.csv")
#head(raw_data)
有些數據前的零會被一些軟體自動省略,然而有些數據的位數非常重要。例如原數據的FIPSno代碼就要求是5位數字,所以需要在不夠五位數字的前加一個零,代碼如下所示:
# add leading zeros to fill in 5 digits.
raw_data %>%
mutate(FIPS_no = str_pad(FIPSno, 5, pad = "0" )) %>%
select(FIPS_no)
## # A tibble: 3,111 x 1
## FIPS_no
## <chr>
## 1 01001
## 2 01003
## 3 01005
## 4 01007
## 5 01009
## 6 01011
## 7 01013
## 8 01015
## 9 01017
## 10 01019
## # ... with 3,101 more rows
原始數據最大的特點就是列名也包含了數據,例如第7到第10列名稱為:「farmN1987」 「nonfN1987」 「farmN1988」 「nonfN1988」。列名中包括了類別 (farm 與 nonf), 肥料種類(N 與 P)和年份(1987)。
基本步驟包括:
移除不需要的信息,
將所有的施肥量數據放到一列,
將列名中的數據分離出來。
clean_data = raw_data %>% # 移除不需要的信息.
select(-c(FIPS_st, FIPS_co, FIPSno)) %>% # 將寬型數據轉換成列數據。
gather(Fert.Type, Quantity, farmN1987:nonfP2012) %>% # 將三個變量(variables)分離出來。
mutate(Year = str_sub(Fert.Type, start = -4),
Nutrient = str_sub(Fert.Type, start = -5, end = -5),
Farm.Type = str_sub(Fert.Type, start = 1, end = 4)
) %>% # 移除不需要的數據
select(-Fert.Type)
head(clean_data)
## # A tibble: 6 x 7
## FIPS State County Quantity Year Nutrient Farm.Type
## <chr> <chr> <chr> <int> <chr> <chr> <chr>
## 1 01001 AL Autauga 1580225 1987 N farm
## 2 01003 AL Baldwin 6524369 1987 N farm
## 3 01005 AL Barbour 2412372 1987 N farm
## 4 01007 AL Bibb 304592 1987 N farm
## 5 01009 AL Blount 1825118 1987 N farm
## 6 01011 AL Bullock 767573 1987 N farm
到這裡,數據已經基本已經滿足了Tidy 數據的要求。考慮到農場類型的兩個水平為farm 和 nonf, 尤其是nonf容易引起大家的誤解,筆者將所有的nonf 替換成 nonfarm.
clean_data = clean_data %>%
# 將 nonf 替換成 nonfarm
mutate(Farm.Type = ifelse(Farm.Type == "nonf",
"nonfarm", "farm"))
# 農場類型已經成功替換成了 nonfarm.
tail(clean_data$Farm.Type)
## [1] "nonfarm" "nonfarm" "nonfarm" "nonfarm" "nonfarm" "nonfarm"
數據可視化舉例整理後的數據可以很方便的進行數據可視化,筆者以ggplot2為例來示範Tidy數據的可視化應用。例如我們可以列出2003年美國磷肥肥施用量最多的10個州,如下圖所示。
Take-home pointsThe end, thanks for reading.
專注分享商業數據分析、金融數據分析、應用統計分析、知識圖譜、機器學習、計量經濟、人工智慧、網絡爬蟲、自動化報告與可重複研究等熱門技術內容。定向培養Stata、Python、R語言數據人才,助力產學研政企商協同發展,為中國大數據產業蓄能。合作熱線:010-56451129 郵箱:info@uone-tech.cn。