R語言 實現將1對多數據與1對1數據互換
想瞭好長時間名字,不知道要解決的問題的名字叫什麼,直接上問題demo
問題demo
現在有用戶消費金額的數據:
用戶 | 日期 | 金額 |
---|---|---|
小明 | 2016-01 | 300 |
小明 | 2016-02 | 500 |
小明 | 2016-03 | 400 |
小劉 | 2016-01 | 700 |
小劉 | 2016-02 | 800 |
小劉 | 2016-03 | 600 |
我將以上數據格式為一對多數據(想不出好名字,敬請大傢拍磚)
還有一種數據形式如下,我將如下格式數據稱為1對1數據
用戶 | 2016-01 | 2016-02 | 2016-03 |
---|---|---|---|
小明 | 300 | 500 | 400 |
小劉 | 700 | 800 | 600 |
如何用R語言實現1對多數據與1對1數據之間的互換,在這裡寫瞭一個簡單的小函數,大傢有好的想法敬請提出。
生成1對1數據集的代碼如下:
#創建數據集 c1<-c("小明",300,500,400) c2<-c("小劉",700,800,600) dt<-as.data.frame(rbind(c1,c2)) names(dt)<-c("用戶","2016-01","2016-02","2016-03")
1對1數據轉成1對多數據
構建1對多數據的轉換函數:
##data原始數據集 ##colList要變換的列 ##要保留的主鍵列 One2More<-function(data,colList,primaryCol){ result=data.frame(NULL) for(r in c(1:nrow(data))){ temp<-as.data.frame(t(data[r,colList])) temp$日期<-row.names(temp) temp<-cbind(temp,data[r,primaryCol]) names(temp)<-c("c1","c2","c3")#臨時起的名字,可按自己需求進行修改 #編行號開始,如果沒有要求,此步可省略 resultRows<-nrow(result) tempRows<-nrow(temp) row.names(temp)<-c((resultRows+1):(resultRows+tempRows)) #編行號結束 result<-rbind(result,temp) } result; }
執行代碼如下:
One2MoreResult<-One2More(dt,c("2016-01","2016-02","2016-03"),"用戶")
結果如下圖所示:
1對多數據轉成1對1數據
針對多轉一我們需要安裝plyr包,函數如下:
#如果有plyr,請跳過此步安裝 install.packages("plyr") library(plyr) ##data:數據集 ##primaryCol:要分組的那一列 ##rowNameCols:想要變成表頭的列 More2One<-function(data,primaryCol,rowNameCols){ ddply(data,primaryCol,function(k){colNames<-k[,rowNameCols];row.names(k)<-k[,rowNameCols];k<-k[,-c(which(colnames(k)==rowNameCols | colnames(k)==primaryCol ))];t(k)}) }
註意:如果使用上文中One2MoreResult數據,請註意數據類型,得出的數值結果為因子類型,請先進行轉換,轉換代碼如下:
One2MoreResult$c1<-as.numeric(as.character(One2MoreResult$c1))
此時One2MoreResult的數據如下:
此時要按照c3進行分組,將c2列放在表頭去
執行代碼如下:
More2OneResult<-More2One(One2MoreResult,"c3","c2")
結果如下圖所示:
完整代碼
#創建數據集 c1<-c("小明",300,500,400) c2<-c("小劉",700,800,600) dt<-as.data.frame(rbind(c1,c2)) View(dt) names(dt)<-c("用戶","2016-01","2016-02","2016-03") ##data原始數據集 ##colList要變換的列 ##要保留的主鍵列 One2More<-function(data,colList,primaryCol){ result=data.frame(NULL) for(r in c(1:nrow(data))){ temp<-as.data.frame(t(data[r,colList])) temp$日期<-row.names(temp) temp<-cbind(temp,data[r,primaryCol]) names(temp)<-c("c1","c2","c3") #編行號開始,如果沒有要求,此步可省略 resultRows<-nrow(result) tempRows<-nrow(temp) row.names(temp)<-c((resultRows+1):(resultRows+tempRows)) #編行號結束 result<-rbind(result,temp) } result; } #如果有plyr,請跳過此步安裝 install.packages("plyr") library(plyr) ##data:數據集 ##primaryCol:要分組的那一列 ##rowNameCols:想要變成表頭的列 More2One<-function(data,primaryCol,rowNameCols){ ddply(data,primaryCol,function(k){colNames<-k[,rowNameCols];row.names(k)<-k[,rowNameCols];k<-k[,-c(which(colnames(k)==rowNameCols | colnames(k)==primaryCol ))];t(k)}) } One2MoreResult<-One2More(dt,c("2016-01","2016-02","2016-03"),"用戶") View(One2MoreResult) One2MoreResult$c1<-as.numeric(as.character(One2MoreResult$c1)) More2OneResult<-More2One(One2MoreResult,"c3","c2") View(More2OneResult)
期望
如果有時間會解決如下問題:
1. 提高代碼的通用性
2. 列名或表頭名可以通過指定來解決
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。
推薦閱讀:
- R語言中矩陣matrix和數據框data.frame的使用詳解
- R語言的Dataframe常用操作使用
- R語言數據結構之矩陣、數組與數據框詳解
- R語言中的vector(向量),array(數組)使用總結
- R語言數據類型知識點總結