本文讲述思路如下
list 转化为 data.frame(分为两种情况)
data.frame 转化为 list
matrix 转化为 list
list的转置
参考资料
分为以下两种情况
list 的每个元素作为一列
list 的每个元素作为一行(包括了list转化为matrix的部分)
(1)list 的每个元素作为一列
下面代码的讲述思路为
先转换最简单的list(l)
然后再让list变复杂一些(ll),用多种方法进行转换
最后再复杂一点,编写函数进行转换
# 1.最简单的list l <- list(1:4,2:5) as.data.frame(l) # 生成4*2的数据框 data.frame(l) # 结果同上 # 复杂一点 # 一个更复杂的list,两层list,代表不同组别,需要分别转化为数据框,然后拼接在一起 ll <- list(a = list(x = 1:10, y = 2:11, group = 1), b = list(x = 11:20, y = 12:21, group = 2)) # 一法 dfll <- do.call(rbind,lapply(ll, data.frame)) dfll # 二法,使用plyr包中的函数 library (plyr) df <- ldply (ll, data.frame) df # 三法,使用data.table包中的函数 library(data.table) ll0 <- list(a = list(x = 1:10, y = 2:11), b = list(x = 11:20, y = 12:21)) rbindlist(ll0) # 此函数无法处理ll,因为无法循环对应 # 再复杂一点 # 如果其中有一列是我们不想要的,需要先提取再转化为data.frame ll1 <- list(a = list(x = 1:10, y = 2:11, z = 1:3), b = list(x = 11:20, y = 12:21, z = 1:3)) # 如果直接使用这条命令,会报错 # do.call(rbind,lapply(ll1, data.frame)) # 因为10不是3的倍数,无法循环对应,所以我们要把z这列去掉 f <- function(x){ data.frame(x[1:2]) } do.call(rbind,lapply(ll1, f))
(2)list 的每个元素作为一行
这里的一些方法其实是先转化成这样的矩阵,再将矩阵转化为数据框的,所以下文list转化为矩阵的这部分就不再赘述
# 变成向量之后再转化为矩阵,再转化为数据框 df <- data.frame(matrix(unlist(l), nrow=2, byrow=T),stringsAsFactors=FALSE) df # 使用rbind.data.frame函数 # a <- rbind.data.frame(l) 不可以这样使用 do.call(rbind.data.frame, l) # do.call 函数是将前面函数的参数放在一个list中使用,正好l是这样一个list,它表示该函数的多个参数,而不是第一个参数是这个list # 用sapply将每一个元素变成向量,组成一个矩阵。下面两种写法等价 data.frame(t(sapply(l,c))) data.frame(t(sapply(l, `[`))) # 使用Reduce函数实现累加效果 data.frame(Reduce(rbind, l)) # 像累加一样,每一个元素拿出来作为rbind的参数,和之前结合的结果再一次结合
我们要实现如下转化
每一列作为list的一个元素
每一行作为list的一个元素
对行进行分组,每一组作为list的一个元素
df <- data.frame(x=1:4,y=2:5,z=rep(1:2,2)) # 先看看list和as.list函数的结果是什么样的 as.list(df) # 每一列对应list的一个元素 list(df) # 一整个数据框成为list的一个元素 split(df, 1:4) # 每一行作为list的一个元素 split(df, df$z) # 按照z列进行分组
我们想将matrix的每一行或者每一列作为list的一个元素,list 和 as.list 函数不能实现,前者是将整个矩阵作为list的一个元素,后者是将每一个值作为list的一个元素
我们使用如下方法实现这一过程
# matrix的每一列作为list的一个元素 mat <- matrix(c(1:4,2:5), byrow=F,ncol=2) # 下面每一行都可以实现 tapply(mat,rep(1:ncol(mat),each=nrow(mat)),function(i)i) # 分组计算生成一个list split(mat, rep(1:ncol(mat), each = nrow(mat))) split(mat, col(mat)) # 更简洁的写法 as.list(as.data.frame(mat)) # 速度比较慢 lapply(seq_len(ncol(mat)), function(i) mat[,i]) plyr::alply(mat,2) # matrix的每一行作为list的一个元素 # 一种方法是将mat转置之后用上面的方法,还有下面两种方法 split(mat, row(mat)) lapply(seq_len(nrow(mat)), function(i) mat[i,])
这部分对两个类型的list进行转置
ax <- data.frame(a=1,x=2) ay <- data.frame(a=3,y=4) bw <- data.frame(b=5,w=6) bz <- data.frame(b=7,z=8) before <- list( a=list(x=ax, y=ay), b=list(w=bw, z=bz)) after <- list(w.x=list(a=ax, b=bw), y.z=list(a=ay, b=bz)) before after # 实现将 before 转换成after形式,其实就是对列表进行转置 # 另外一个例子,list 中的元素是向量而不是list l <- list(1:4,1:4)
下面使用几种方法实现
# 第一种方法,使用 data.table 和 purrr 包中现成的函数 # data.table::transpose(before) # 处理不了 purrr::transpose(before) data.table::transpose(l) # list 的每个元素是向量 purrr::transpose(l) # list的每个元素还是list # 第二种方法,自己编写函数 # 下面两行结果和 purrr::transpose 相同 lapply(1:2, function(i) lapply(before, "[[", i)) lapply(1:4, function(i) lapply(l, "[[", i)) lapply(1:4, function(i) sapply(l, "[[", i)) # 和 data.table::transpose 一样 lapply(1:2, function(i) sapply(before, "[[", i)) # 将 list 的元素组合在一起了 # 第三种方法,转化为数据框 # 使用更灵活的data.table dt = as.data.table(before) as.list(data.table(t(dt))) dt = as.data.table(l) as.list(data.table(t(dt))) dt = as.data.frame(l) # 这时可以用data.frame as.list(data.table(t(dt))) # 使用data.frame也可以,但是要先转化为矩阵 new <- do.call(rbind, before) as.list(data.frame(new))
最后一次推荐 rstudio 快捷键
ctrl + up/down 上下滚动界面
ctrl + enter 运行该行程序,同时光标换行换行
alt + enter 运行该行程序,光标不换行
更多快捷键在 rstudio 菜单栏中的 help-keyboard shortcuts help 中查询
往期回顾
R数据处理|基础篇(一)
R数据处理|基础篇(二)
R数据处理|data.table篇(一)
R数据处理|data.table篇(二)
R数据处理|data.table篇(三)
R深入 | 数据类型
R | 基础绘图
R|ggplot2(一)|一个完整的绘图流程
R|数据处理|merge数据详解