R語言 數據集行列互換的技巧分享

現在給大傢介紹的數據處理技巧是長轉寬,也就相當於Excel中的轉置,不過用R語言實現的長轉寬還有數據合並的功能,自然比Excel強大多瞭。

這裡給大傢介紹4個函數,其中melt()、dcast()來自reshape2包,gather()、spread()來自tidyr包

一、寬轉長——melt()、gather()

mydata<-data.frame(
 name=c("store1","store2","store3","store4"),
 address=c("普陀區","黃浦區","徐匯區","浦東新區"),
 sale2014=c(3000,2500,2100,1000),
 sale2015=c(3020,2800,3900,2000),
 sale2016=c(5150,3600,2700,2500),
 sale2017=c(4450,4100,4000,3200)
)
#寬轉長——melt
mydata1<-melt(
 mydata,
 id.vars=c("address","name"),#要保留的主字段
 variable.name = "Year",#轉換後的分類字段名稱(維度)
 value.name = "Sale" #轉換後的度量值名稱
)

輸出結果

> mydata1<-melt(
+ mydata,
+ id.vars=c("address","name"),#要保留的主字段
+ variable.name = "Year",#轉換後的分類字段名稱(維度)
+ value.name = "Sale" #轉換後的度量值名稱
+ )
> mydata1
 address name  Year Sale
1 普陀區 store1 sale2014 3000
2 黃浦區 store2 sale2014 2500
3 徐匯區 store3 sale2014 2100
4 浦東新區 store4 sale2014 1000
5 普陀區 store1 sale2015 3020
6 黃浦區 store2 sale2015 2800
7 徐匯區 store3 sale2015 3900
8 浦東新區 store4 sale2015 2000
9 普陀區 store1 sale2016 5150
10 黃浦區 store2 sale2016 3600
11 徐匯區 store3 sale2016 2700
12 浦東新區 store4 sale2016 2500
13 普陀區 store1 sale2017 4450
14 黃浦區 store2 sale2017 4100
15 徐匯區 store3 sale2017 4000
16 浦東新區 store4 sale2017 3200

再來看看gather()函數怎麼用

> #寬轉長——gather
> mydata1<-tidyr::gather(
+ data=mydata,
+ key="Year",
+ value="sale",
+ sale2014:sale2017
+ )
> mydata1
  name address  Year sale
1 store1 普陀區 sale2014 3000
2 store2 黃浦區 sale2014 2500
3 store3 徐匯區 sale2014 2100
4 store4 浦東新區 sale2014 1000
5 store1 普陀區 sale2015 3020
6 store2 黃浦區 sale2015 2800
7 store3 徐匯區 sale2015 3900
8 store4 浦東新區 sale2015 2000
9 store1 普陀區 sale2016 5150
10 store2 黃浦區 sale2016 3600
11 store3 徐匯區 sale2016 2700
12 store4 浦東新區 sale2016 2500
13 store1 普陀區 sale2017 4450
14 store2 黃浦區 sale2017 4100
15 store3 徐匯區 sale2017 4000
16 store4 浦東新區 sale2017 3200

和melt()函數不同,gather()函數需要指定關鍵字段key,以及關鍵字段對應的值value,但是gather()函數更加好理解。

二、長轉寬——dcast()和spread()

還是用上面的data1數據集,先來看看dcast()函數

#長轉寬——dcast
dcast(
 data=mydata1,
 name+address~Year
 #左側是要保留的字段,右側是要分割的分類變量,列數等於表達式
 #右側分類變量的類別個數
)
> #長轉寬——dcast
> dcast(
+ data=mydata1,
+ name+address~Year
+ #左側是要保留的字段,右側是要分割的分類變量,列數等於表達式
+ #右側分類變量的類別個數
+ )
Using sale as value column: use value.var to override.
 name address sale2014 sale2015 sale2016 sale2017
1 store1 普陀區  3000  3020  5150  4450
2 store2 黃浦區  2500  2800  3600  4100
3 store3 徐匯區  2100  3900  2700  4000
4 store4 浦東新區  1000  2000  2500  3200

dcast()函數的使用規則需要琢磨下才能理解,大傢好好看看註釋部分,再來看看spread()

#長轉寬——spread
tidyr::spread(
 data=mydata1,
 key=Year,
 value=sale
)
> #長轉寬——spread
> tidyr::spread(
+ data=mydata1,
+ key=Year,
+ value=sale
+ )
 name address sale2014 sale2015 sale2016 sale2017
1 store1 普陀區  3000  3020  5150  4450
2 store2 黃浦區  2500  2800  3600  4100
3 store3 徐匯區  2100  3900  2700  4000
4 store4 浦東新區  1000  2000  2500  3200

直接調用tidyr::spread,需要指定關鍵字段key和對應的值value。

但是從理解上來看,我個人更喜歡tidyr包的函數,使用很清晰,大傢可以根據實際情況自行選擇,好啦,今天的分享結束,下次再見!

補充:利用R語言對數據行列轉制

使用軟件:R語言,mysql

使用系統:ubuntu16.04

使用效果前後對比:

使用前

x1 x2 y
a A 1
b B 2
c C 3
a A 4

使用後(裡面的數值可以進行多種變換,主要是把x1,x2改為他們的交叉表)

A B C
a 5(1+4) NA NA
b NA 2 NA
c NA NA 3

1.R語言與mysql的數據庫連接

下載RMysql(由於我使用的是ubuntu,所以使用RMysql):

install.packages("RMySQL")

加載所需要的程輯包:

library(RMySQL)

將mysql數據導入R:

con<-dbConnect(MySQL(),dbname="database_name",user="user_name",password="password")

導入後,所得數據類型是數據框(data.frame)

對於RMySQL這個包,比較重要的語句有這幾個:

summary(con) : 用於查看con對應的mysql信息

dbListTables(con) :用於查看con中的所有table

dbRemoveTable(con,”table_name”)

dbReadTable(con,”table_name”)

dbWriteTable(con,”table_name”,value) 其中value類型需要為數據框

2.在R中實現數據變換

我們使用以上的語句,讀取所需要變換的表

data=dbReadTable(con,"table_name")

然後使用一個重要的函數:tapply()

註意,我下面使用的是我之前舉例所用的表

data2=tapply(data\$y,list(data\$x1,data$x2),sum)

對於tapply(x,list(a,b),fac)

a和b是形成交叉表的行列表頭

而x則是取值,我們當然可以不使用data裡面的值當作x

fac則是對x進行的函數運算,比如使用sum,就是將相同的x1,x2的y相加

3.將數據導回mysql

上面我們已經把數據變換為想要的表格形式瞭,不過,使用瞭tapply後,data2的類會變為矩陣(matrix),要想知道數據類型,在R中使用class()便可以查看,而我們所使用的RMySQL包將r中數據寫入mysql是需要用數據框的,所以我們要轉換矩陣為數據框,那麼要怎麼做呢,很簡單

data3=data.frame(data2)

這樣,我們的data3便是一個數據框瞭,使用語句

dbWriteTable(con,test,data3)

便寫入瞭一個table於mysql,名字叫做test,數據值為data3.

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。