2012-02-12 31 views
6

Tôi có một danh sách trong đó mỗi mục danh sách là một bảng tần số từ bắt nguồn từ việc sử dụng "bảng()" trên một văn bản mẫu khác. Mỗi bảng, do đó, một chiều dài khác nhau. Bây giờ tôi muốn chuyển đổi danh sách thành một khung dữ liệu duy nhất trong đó mỗi cột là một từ mỗi hàng là một văn bản mẫu. Dưới đây là một ví dụ điển hình nộm của dữ liệu của tôi:Kết hợp các bảng tần số vào một khung dữ liệu đơn

t1<-table(strsplit(tolower("this is a test in the event of a real word file you would see many more words here"), "\\W")) 

t2<-table(strsplit(tolower("Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal"), "\\W")) 

t3<-table(strsplit(tolower("Ask not what your country can do for you - ask what you can do for your country"), "\\W")) 

myList <- list(t1, t2, t3) 

như vậy, một bị loại cấu trúc này:

> class(myList[[3]]) 
[1] "table" 

> myList[[3]] 

     ask  can country  do  for  not what  you your 
    2  2  2  2  2  2  1  2  2  2 

bây giờ tôi cần phải chuyển đổi danh sách này (myList) vào một khung dữ liệu duy nhất. Tôi nghĩ rằng tôi có thể làm điều này với plyr, dọc theo dòng của những gì được thực hiện ở đây (http://ryouready.wordpress.com/2009/01/23/r-combining-vectors-or-data-frames-of-unequal- length-into-one-data-frame /), ví dụ

library(plyr) 
l <- myList 
do.call(rbind.fill, l) 

Nhưng có vẻ như đối tượng "bảng" của tôi không phát đẹp. Tôi đã thử chuyển đổi chúng thành dfs và cũng thành vectơ, nhưng không có gì trong số đó hoạt động hoàn toàn đúng.

+0

oh chờ đợi, trong câu trả lời của tôi Tôi giả định bạn muốn có một cột dữ liệu riêng biệt. Khung cho mỗi bảng .. Bạn có phải là định dạng khác không? –

Trả lời

4
freqs.list <- mapply(data.frame,Words=seq_along(myList),myList,SIMPLIFY=FALSE,MoreArgs=list(stringsAsFactors=FALSE)) 
freqs.df <- do.call(rbind,freqs.list) 
res <- reshape(freqs.df,timevar="Words",idvar="Var1",direction="wide") 
head(res) 
+0

Gregory, giải pháp này là hiệu quả nhất, cảm ơn! – litlogger

1

Đây là cách không phù hợp để hoàn thành công việc. Tôi chắc chắn có một 1-liner ngoài kia chỉ cho điều này, nhưng tôi dunno nơi một trong hai:

myList <- list(t1=t1, t2=t2, t3=t3) 
    myList <- lapply(myList,as.data.frame,stringsAsFactors = FALSE) 
    Words <- unique(unlist(lapply(myList,function(x) x[,1]))) 
    DFmerge <- data.frame(Words=Words) 
    for (i in 1:3){ 
     DFmerge <- merge(DFmerge,myList[[i]],by.x="Words",by.y="Var1",all.x=TRUE) 
    } 
    colnames(DFmerge) <- c("Words","t1","t2","t3") 

Và nhìn xung quanh một chút, đây là một cách khác để cung cấp cho sản lượng tương tự như trong bài đăng blog liên kết : [Edit: works now]

myList <- list(t1=t1, t2=t2, t3=t3) 
    myList <- lapply(myList,function(x) { 
     A <- as.data.frame(matrix(unlist(x),nrow=1)) 
     colnames(A) <- names(x) 
     A[,colnames(A) != ""] 
     } 
    ) 
    do.call(rbind.fill,myList) 

Cũng xấu xí, vì vậy có thể một câu trả lời hay hơn sẽ vẫn xuất hiện.

+0

Cảm ơn Tim, tôi đã hy vọng tránh được vòng lặp, nhưng điều này dường như đã hoàn thành công việc. Sau đó tôi có thể chuyển đổi các df và làm một chút cắt tỉa để từ đó là tên cột. . . vẫn còn, dường như với tôi có phải là một giải pháp dựa trên plyr. . . . – litlogger

+0

@litlogger phương pháp thứ hai, vẫn xấu xí, hiện đang hoạt động và tránh vòng lặp cho –

+0

và tôi nên đề cập đến, các dấu chấm câu, ví dụ: '" - "' biến thành '" "' trong 'tên (x)', và điều này gây ra lỗi cho 'rbind.fill()'. Tôi ném chúng ra trong chức năng ẩn danh 'lapply'. Chỉ cần FYI, trong trường hợp đó là không mong muốn –

7

1. zoo. Gói sở thú có chức năng phối hợp đa phương tiện có thể thực hiện điều này một cách gọn gàng. Các lapply chuyển đổi từng phần của myList đến một đối tượng sở thú và sau đó chúng tôi chỉ đơn giản là kết hợp chúng tất cả:

# optionally add nice names to the list 
names(myList) <- paste("t", seq_along(myList), sep = "") 

library(zoo) 
fz <- function(x)with(as.data.frame(x, stringsAsFactors=FALSE), zoo(Freq, Var1))) 
out <- do.call(merge, lapply(myList, fz)) 

các lợi nhuận trên một vườn thú loạt đa biến, trong đó "lần" là "a", "ago", vv nhưng nếu một dữ liệu kết quả khung hình đã được mong muốn sau đó nó chỉ là một vấn đề của as.data.frame(out).

2. Giảm. Đây là giải pháp thứ hai. Nó sử dụng Reduce trong lõi của R.

merge1 <- function(x, y) merge(x, y, by = 1, all = TRUE) 
out <- Reduce(merge1, lapply(myList, as.data.frame, stringsAsFactors = FALSE)) 

# optionally add nice names 
colnames(out)[-1] <- paste("t", seq_along(myList), sep = "") 

3. xtabs. Cái này cho biết thêm tên vào danh sách và sau đó trích xuất các tần số, tên và các nhóm như một vector dài từng đưa họ trở lại với nhau sử dụng xtabs:

names(myList) <- paste("t", seq_along(myList)) 

xtabs(Freq ~ Names + Group, data.frame(
    Freq = unlist(lapply(myList, unname)), 
    Names = unlist(lapply(myList, names)), 
    Group = rep(names(myList), sapply(myList, length)) 
)) 

Benchmark

Benchmarking một số các giải pháp sử dụng rbenchmark gói chúng tôi nhận được sau đây chỉ ra rằng giải pháp sở thú là nhanh nhất trên dữ liệu mẫu và được cho là đơn giản nhất là tốt.

> t1<-table(strsplit(tolower("this is a test in the event of a real word file you would see many more words here"), "\\W")) 
> t2<-table(strsplit(tolower("Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal"), "\\W")) 
> t3<-table(strsplit(tolower("Ask not what your country can do for you - ask what you can do for your country"), "\\W")) 
> myList <- list(t1, t2, t3) 
> 
> library(rbenchmark) 
> library(zoo) 
> names(myList) <- paste("t", seq_along(myList), sep = "") 
> 
> benchmark(xtabs = { 
+ names(myList) <- paste("t", seq_along(myList)) 
+ xtabs(Freq ~ Names + Group, data.frame(
+ Freq = unlist(lapply(myList, unname)), 
+ Names = unlist(lapply(myList, names)), 
+ Group = rep(names(myList), sapply(myList, length)) 
+)) 
+ }, 
+ zoo = { 
+ fz <- function(x) with(as.data.frame(x, stringsAsFactors=FALSE), zoo(Freq, Var1)) 
+ do.call(merge, lapply(myList, fz)) 
+ }, 
+ Reduce = { 
+ merge1 <- function(x, y) merge(x, y, by = 1, all = TRUE) 
+ Reduce(merge1, lapply(myList, as.data.frame, stringsAsFactors = FALSE)) 
+ }, 
+ reshape = { 
+ freqs.list <- mapply(data.frame,Words=seq_along(myList),myList,SIMPLIFY=FALSE,MoreArgs=list(stringsAsFactors=FALSE)) 
+ freqs.df <- do.call(rbind,freqs.list) 
+ reshape(freqs.df,timevar="Words",idvar="Var1",direction="wide") 
+ }, replications = 10, order = "relative", columns = c("test", "replications", "relative")) 
    test replications relative 
2  zoo   10 1.000000 
4 reshape   10 1.090909 
1 xtabs   10 1.272727 
3 Reduce   10 1.272727 

THÊM: giải pháp thứ hai.

THÊM: giải pháp thứ ba.

THÊM: điểm chuẩn.

+0

Cảm ơn G. nhưng khi tôi chạy ví dụ mã của bạn, tôi nhận được một lỗi: Lỗi trong eval (thay thế (expr), dữ liệu, enclos = parent.frame()): số 'envir' arg không có chiều dài một – litlogger

+0

@litlogger, đã sửa nó. –

Các vấn đề liên quan