R語言實現倫敦各地區預期壽命與全國平均水平差異地理資料視覺化(熱力圖)

Hotomoderato_Han發表於2020-10-30

R語言實現倫敦各地區預期壽命與全國平均水平差異地理資料視覺化

讀取csv檔案

使用read.csv()直接從web讀取並在數字列中清除文字字元

read.csv( ) 與 read_csv( ) 區別

read.csv( )read_csv( )
R中預設的csv讀取方式readr包提供的讀取方式
適用於小檔案適用於較大csv檔案
LondonData <- read_csv("https://files.datapress.com/london/dataset/ward-profiles-and-atlas/2015-09-24T14:21:24/ward-profiles-excel-version.csv",
                       locale = locale(encoding = "UTF-8"),
                       na = "n/a")

encoding = “UTF-8” , 在UTF-8中每個字元可以包含一個以上的位元組,但是R中預設的編碼方式為latin1,所以需要修改編碼方式。

檢查是否正確讀入資料

方法一

使用class( )

class(LondonData)

輸出

## [1] "spec_tbl_df" "tbl_df"      "tbl"         "data.frame"

方法二

使用dplyr包中的summarise_all( )和pivot_longer( )檢視變數與變數型別

Datatypelist <- LondonData %>% 
  summarise_all(class) %>%
  pivot_longer(everything(), 
               names_to="All_variables", 
               values_to="Variable_class")

Datatypelist

輸出

# A tibble: 67 x 2
   All_variables                      Variable_class
   <chr>                              <chr>         
 1 Ward name                          character     
 2 Old code                           character     
 3 New code                           character     
 4 Population - 2015                  numeric       
 5 Children aged 0-15 - 2015          numeric       
 6 Working-age (16-64) - 2015         numeric       
 7 Older people aged 65+ - 2015       numeric       
 8 % All Children aged 0-15 - 2015    numeric       
 9 % All Working-age (16-64) - 2015   numeric       
10 % All Older people aged 65+ - 2015 numeric       
# … with 57 more rows

資料篩選

這時所有數字列均已經以數字形式讀入,現在已經有一些資料讀入R,我們需要選擇一個小的子集,只選取倫敦的資料進行處理。因為倫敦自治市的程式碼以E09開頭(檔案其餘部分的區號以E05開頭)所以使用filter( )函式選取需要的資料子集(類似於SQL中的select * from…where…)。
這時候問題又出現了,New code列使用的是字元格式而非整數,在這種情況下我們可以使用str_detect ( ) (stringr字元處理包)與filter ( ) 結合使用。

LondonBoroughs<- LondonData %>% 
  filter(str_detect(`New code`, "^E09"))

檢查輸出結果

LondonBoroughs$`Ward name`

資料提取

異常資料處理

這個時候又出現問題了,發現City of London有兩行,所以提取唯一行,使用distinct( ):

LondonBoroughs<-LondonBoroughs %>%
  distinct()

這樣就OK了!

在這裡插入圖片描述
由於現在在對 “borough” 進行統計而不是“ward”,這樣的命名容易產生誤導,所以最好養成良好的習慣對列名進行重新命名保持一致性。

library(janitor)

LondonBoroughs <- LondonBoroughs %>%
  dplyr::rename(Borough=`Ward name`)%>%
  clean_names()

資料處理

計算:
a. 平均預期壽命
b. 基於a的每個地區的歸一化值
使用mutate( ) 在現有變數的基礎上增加新變數

Life_expectancy <- LondonBoroughs %>% 
  #平均男女預期壽命
  mutate(averagelifeexpectancy= (female_life_expectancy_2009_13 +
                                   male_life_expectancy_2009_13)/2)%>%
  #歸一化壽命
  mutate(normalisedlifeepectancy= averagelifeexpectancy /
           mean(averagelifeexpectancy))%>%
  #挑選需要的列
  select(new_code,
         borough,
         averagelifeexpectancy, 
         normalisedlifeepectancy)%>%
  #降序排列
  arrange(desc(normalisedlifeepectancy))

c. 使用case_when( )比較各地區預期壽命與英國平均壽命81.16

Life_expectancy2 <- Life_expectancy %>%
  mutate(UKcompare = case_when(averagelifeexpectancy>81.16 ~ "above UK average",
                               TRUE ~ "below UK average"))
Life_expectancy2

在這裡插入圖片描述
d. 計算兩者差值

Life_expectancy2_group <- Life_expectancy2 %>%
  mutate(UKdiff = averagelifeexpectancy-81.16) %>%
  group_by(UKcompare)%>%
  summarise(range=max(UKdiff)-min(UKdiff), count=n(), Average=mean(UKdiff))

在這裡插入圖片描述
e.根據差值對區域進行統計
1) 將列UKdiff舍入到0個小數位(不新增新列)
2) 使用case_when()發現有相等的平均年齡或超過81的區域,並基於文字的合併“equal or above UK average by” 建立一個新的列containts,然後在UKdiff劃分差異年數。通過str_c()函式,將兩個或多個向量元素連線到單個字元向量, sep確定如何將這兩個向量隔開。
3)按UKcompare列分組。
4)計算每組中的區域數。

Life_expectancy3 <- Life_expectancy %>%
  mutate(UKdiff = averagelifeexpectancy-81.16)%>%
  mutate(across(where(is.numeric), round, 3))%>%
  mutate(across(UKdiff, round, 0))%>%
  mutate(UKcompare = case_when(averagelifeexpectancy >= 81 ~ 
                                 str_c("equal or above UK average by",
                                       UKdiff, 
                                       "years", 
                                       sep=" "), 
                               TRUE ~ str_c("below UK average by",
                                            UKdiff,
                                            "years",
                                            sep=" ")))%>%
  group_by(UKcompare)%>%
  summarise(count=n())

在這裡插入圖片描述

熱力圖視覺化

使用maptools

install.packages("maptools")
install.packages(c("classInt", "tmap"))

# might also need these ones
install.packages(c("RColorBrewer", "sp", "rgeos", 
                   "tmaptools", "sf", "downloader", "rgdal", 
                   "geojsonio"))

直接從opendata讀取GeoJson檔案

# this will take a few minutes
EW <- st_read("https://opendata.arcgis.com/datasets/8edafbe3276d4b56aec60991cbddda50_2.geojson")

下載讀取shp資料

# shapefile in local folder
EW <- st_read(here::here("prac2_data",
                        "Local_Authority_Districts__December_2015__Boundaries-shp",
                        "Local_Authority_Districts__December_2015__Boundaries.shp"))

查詢倫敦的地區並繪製圖形

LondonMap<- EW %>%
  filter(str_detect(lad15cd, "^E09"))

#plot it using the qtm function
qtm(LondonMap)

在這裡插入圖片描述

在建立地圖之前,需要使用merge()將一些屬性資料連線到地圖,但是首先要Janitor再次清理。

LondonData <- clean_names(LondonData)

#直接從web寫入
BoroughDataMap <- EW %>%
  clean_names()%>%
  # . 表示已經載入的資料
  filter(str_detect(lad15cd, "^E09"))%>%
  merge(.,
        LondonData, 
        by.x="lad15cd", 
        by.y="new_code",
        no.dups = TRUE)%>%
  distinct(.,lad15cd, 
           .keep_all = TRUE)

distinct()這意味著僅基於程式碼具有唯一的行,但保留所有其他變數.keep_all=TRUE。如果更改為.keep_all=FALSE(預設設定),則所有其他變數都將被刪除。

使用qtm( ) 快速建立Choropleth貼圖

tmap_mode("plot")

qtm(BoroughDataMap, 
    fill = "rate_of_job_seekers_allowance_jsa_claimants_2015")

在這裡插入圖片描述
不好看! 這真的不好看! 加個底圖吧!
使用read_osm()函式從OpenStreetMap(OSM)中提取底圖tmaptools
st_box()函式在倫敦周圍建立一個框,sf以提取底圖影像

tmaplondon <- BoroughDataMap %>%
  st_bbox(.) %>% 
  tmaptools::read_osm(., type = "osm", zoom = NULL)

tmap進行繪製,新增底圖,新增倫敦的形狀,要對映的屬性,進行顏色劃分的樣式,透明度(alpha),指南針,比例和圖例。

tmap_mode("plot")

tm_shape(tmaplondon)+
tm_rgb()+
tm_shape(BoroughDataMap) + 
tm_polygons("rate_of_job_seekers_allowance_jsa_claimants_2015", 
        style = "jenks",
        palette = "YlOrBr",
        midpoint = NA,
        title = "Rate per 1,000 people",
        alpha = 0.5) + 
  tm_compass(position = c("left", "bottom"),type = "arrow") + 
  tm_scale_bar(position = c("left", "bottom")) +
  tm_layout(title = "Job seekers' Allowance Claimants", legend.position = c("right", "bottom"))

在這裡插入圖片描述

Finally!合併Life_expectancy4map的空間資料EW並對映合併 tmap

Life_expectancy4map <- EW %>%
  merge(.,
        Life_expectancy4, 
        by.x="lad15cd", 
        by.y="new_code",
        no.dups = TRUE)%>%
  distinct(.,lad15cd, 
           .keep_all = TRUE)

tmap_mode("plot")
tm_shape(tmaplondon)+
  tm_rgb()+
  tm_shape(Life_expectancy4map) + 
  tm_polygons("UKdiff", 
              style="pretty",
              palette="Blues",
              midpoint=NA,
              title="Number of years",
              alpha = 0.5) + 
  tm_compass(position = c("left", "bottom"),type = "arrow") + 
  tm_scale_bar(position = c("left", "bottom")) +
  tm_layout(title = "Difference in life expectancy", legend.position = c("right", "bottom"))

在這裡插入圖片描述
這樣就大功告成啦!

第一次用R繪製熱力圖,感覺不管是資料處理還是地圖繪製的工具包都是比較完備的,不用自己寫函式方法,但是還要多熟練一下R的操作。

相關文章