2012-03-30 28 views
5

Tôi đi qua một bảng freq. đếm ngày hôm nay tôi đã phải mở rộng vào một khung dữ liệu của các giá trị thô. Tôi đã có thể làm điều đó nhưng đã tự hỏi nếu có một cách nhanh hơn bằng cách sử dụng gói reshape hoặc data.table?định hình lại dữ liệu (một cách nhanh hơn)

Bảng ban đầu trông như thế này:

i1 i2 i3 i4 m f 
1 0 0 0 0 22 29 
2 1 0 0 0 30 50 
3 0 1 0 0 13 15 
4 0 0 1 0 1 6 
5 1 1 0 0 24 67 
6 1 0 1 0 5 12 
7 0 1 1 0 1 2 
8 1 1 1 0 10 22 
9 0 0 0 1 10 7 
10 1 0 0 1 27 30 
11 0 1 0 1 14 4 
12 0 0 1 1 1 0 
13 1 1 0 1 54 63 
14 1 0 1 1 8 10 
15 0 1 1 1 8 6 
16 1 1 1 1 57 51 

Dưới đây là một lấy dễ dàng các dữ liệu sử dụng dput:

dat <- structure(list(i1 = c(0L, 1L, 0L, 0L, 1L, 1L, 0L, 1L, 0L, 1L, 
0L, 0L, 1L, 1L, 0L, 1L), i2 = c(0L, 0L, 1L, 0L, 1L, 0L, 1L, 1L, 
0L, 0L, 1L, 0L, 1L, 0L, 1L, 1L), i3 = c(0L, 0L, 0L, 1L, 0L, 1L, 
1L, 1L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L), i4 = c(0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), m = c(22L, 30L, 
13L, 1L, 24L, 5L, 1L, 10L, 10L, 27L, 14L, 1L, 54L, 8L, 8L, 57L 
), f = c(29L, 50L, 15L, 6L, 67L, 12L, 2L, 22L, 7L, 30L, 4L, 0L, 
63L, 10L, 6L, 51L)), .Names = c("i1", "i2", "i3", "i4", "m", 
"f"), class = "data.frame", row.names = c(NA, -16L)) 

cách tiếp cận của tôi (s) để định hình lại các dữ liệu (có cách nào nhanh hơn không?):

#step 1: method 1 (in this case binding and stacking uses less code than reshape) 
dat2 <- data.frame(rbind(dat[,1:4], dat[, 1:4]), 
    sex = rep(c('m', 'f'), each=16), 
    n = c(dat$m, dat$f)) 
dat2 

#step 1: method 2  
dat3 <- reshape(dat, direction = "long", idvar = 1:4, 
    varying = list(c("m", "f")), 
    v.names = c("n"), 
    timevar = "sex", 
    times = c("m", "f")) 
    rownames(dat3) <- 1:nrow(dat3) 
    dat3 <- data.frame(dat3) 
    dat3$sex <- as.factor(dat3$sex) 

all.equal(dat3, dat2) #just to show both method 1 and 2 give the same data frame 

#step 2 
dat4 <- dat2[rep(seq_len(nrow(dat2)), dat2$n), 1:5] 
rownames(dat4) <- 1:nrow(dat4) 
dat4 

Tôi cho rằng đây là một vấn đề phổ biến khi bạn muốn lấy một bảng từ một bài báo và tái tạo nó, nó đòi hỏi một số giải nén. Tôi thấy mình làm điều này nhiều hơn và nhiều hơn nữa và muốn chắc chắn rằng tôi đang có hiệu quả.

Trả lời

7

Đây là một lớp lót.

dat2 <- ddply(dat, 1:4, summarize, sex = c(rep('m', m), rep('f', f))) 
2

Tôi sẽ sử dụng melt cho bước đầu tiên và ddply cho bước thứ hai.

library(reshape2) 
library(plyr) 
d <- ddply( 
    melt(dat, id.vars=c("i1","i2","i3","i4"), variable.name="sex"), 
    c("i1","i2","i3","i4","sex"), 
    summarize, 
    id=rep(1,value) 
) 
d$id <- cumsum(d$id) 
+0

Tôi li ke nó tốt hơn so với cách tiếp cận của tôi cho đến nay. Nếu không có ai đến với bất cứ điều gì hiệu quả hơn (viết mã ít hơn không phải là tốc độ) Tôi sẽ đánh dấu này là một câu trả lời đúng. +1 –

+0

Tôi đánh dấu điều này là chính xác. Tôi không nghĩ rằng bất cứ ai có thể đánh bại số lượng mã này. –

+0

kiểm tra lại :-) – Ramnath

5

Và đây là cơ sở một lớp lót.

dat2 <- cbind(dat[c(rep(1:nrow(dat), dat$m), rep(1:nrow(dat), dat$f)),1:4], 
       sex=c(rep("m",sum(dat$m)), rep("f", sum(dat$f)))) 

Hoặc, nói chung là nhiều hơn một chút:

d1 <- dat[,1:4] 
d2 <- as.matrix(dat[,5:6]) 
dat2 <- cbind(d1[rep(rep(1:nrow(dat), ncol(d2)), d2),], 
       sex=rep(colnames(d2), colSums(d2))) 
+0

Làm việc tốt trong cơ sở +1 –

3

Cho rằng không ai đã đăng một giải pháp data.table (như đề xuất trong câu hỏi ban đầu)

library(data.table) 
DT <- as.data.table(dat) 
DT[,list(sex = rep(c('m','f'),c(m,f))), by= list(i1,i2,i3,i4)] 

Hoặc, thậm chí ngắn gọn hơn

DT[,list(sex = rep(c('m','f'),c(m,f))), by= 'i1,i2,i3,i4'] 
+0

Có thể sửa đổi 'c (m, f)' (và 'danh sách (i1, i2, i3, i4)' để chỉ một biến chứa tên cột không? Ví dụ, thay vì m và f cột, nếu tôi có 100 cột (nói Var0 đến Var99) và không muốn gõ tên của mỗi cột. – dnlbrky

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