Dwzb , R語言中文社區專欄作者,廈門大學統計專業學生。
知乎專欄:https://zhuanlan.zhihu.com/Data-AnalysisR
本文講述思路如下
list 轉化為 data.frame分為以下兩種情況
(1)list 的每個元素作為一列
下面代碼的講述思路為
# 1.最簡單的listl <- 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.framell1 <- 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的參數,和之前結合的結果再一次結合
data.frame 轉化為 list我們要實現如下轉化
每一列作為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我們想將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) # 分組計算生成一個listsplit(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 的轉置這部分對兩個類型的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))beforeafter# 實現將 before 轉換成after形式,其實就是對列表進行轉置# 另外一個例子,list 中的元素是向量而不是listl <- 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.tabledt = 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.frameas.list(data.table(t(dt)))# 使用data.frame也可以,但是要先轉化為矩陣new <- do.call(rbind, before) as.list(data.frame(new))
最後一次推薦 rstudio 快捷鍵
更多快捷鍵在 rstudio 菜單欄中的 help-keyboard shortcuts help 中查詢
公眾號後臺回復關鍵字即可學習
回復 爬蟲 爬蟲三大案例實戰
回復 Python 1小時破冰入門
回復 數據挖掘 R語言入門及數據挖掘
回復 人工智慧 三個月入門人工智慧
回復 數據分析師 數據分析師成長之路
回復 機器學習 機器學習的商業應用
回復 數據科學 數據科學實戰
回復 常用算法 常用數據挖掘算法