R语言将1对多数据与1对1数据互换

想了好长时间名字,不知道要解决的问题的名字叫什么,直接上问题demo

问题demo

现在有用户消费金额的数据:

用户日期金额
小明2016-01300
小明2016-02500
小明2016-03400
小刘2016-01700
小刘2016-02800
小刘2016-03600

我将以上数据格式为一对多数据(想不出好名字,敬请大家拍砖)
还有一种数据形式如下,我将如下格式数据称为1对1数据

用户2016-012016-022016-03
小明300500400
小刘700800600

如何用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. 列名或表头名可以通过指定来解决

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值