2012-02-17 26 views
12

Tôi có một khung dữ liệu với độ dài và chiều rộng của động vật chân đốt khác nhau từ ruột của salamanders. Bởi vì một số can đảm có hàng ngàn con mồi nhất định, tôi chỉ đo một tập hợp con của từng loại con mồi. Bây giờ tôi muốn thay thế từng cá nhân không có bảo hiểm với chiều dài và chiều rộng trung bình cho con mồi đó. Tôi muốn giữ khung dữ liệu và chỉ cần thêm các cột được tranh chấp (length2, width2). Lý do chính là mỗi hàng cũng có các cột có dữ liệu về ngày tháng và vị trí mà dấu salamander được thu thập. Tôi có thể điền vào NA với một lựa chọn ngẫu nhiên của các cá nhân được đo nhưng vì lợi ích của lập luận, giả sử tôi chỉ muốn thay thế mỗi NA bằng giá trị trung bình.Làm thế nào để thay thế NA bằng trung bình theo tập hợp con trong R (impute with plyr?)

Ví dụ tưởng tượng tôi có một dataframe trông giống như sau:

id taxa  length width 
101 collembola 2.1  0.9 
102 mite  0.9  0.7 
103 mite  1.1  0.8 
104 collembola NA  NA 
105 collembola 1.5  0.5 
106 mite  NA  NA 

Trên thực tế tôi có nhiều cột và khoảng 25 loài khác nhau và có tổng cộng ~ 30.000 mục con mồi trong tổng số. Nó có vẻ như gói plyr có thể là lý tưởng cho việc này nhưng tôi không thể tìm ra cách để làm điều này. Tôi không phải là R hay hiểu biết về lập trình nhưng tôi đang cố học.

Không phải là tôi biết mình đang làm gì nhưng tôi sẽ cố tạo một tập dữ liệu nhỏ để chơi nếu nó có ích.

exampleDF <- data.frame(id = seq(1:100), taxa = c(rep("collembola", 50), rep("mite", 25), 
rep("ant", 25)), length = c(rnorm(40, 1, 0.5), rep("NA", 10), rnorm(20, 0.8, 0.1), rep("NA", 
5), rnorm(20, 2.5, 0.5), rep("NA", 5)), width = c(rnorm(40, 0.5, 0.25), rep("NA", 10), 
rnorm(20, 0.3, 0.01), rep("NA", 5), rnorm(20, 1, 0.1), rep("NA", 5))) 

Dưới đây là một vài điều tôi đã cố gắng (mà chưa từng làm việc):

# mean imputation to recode NA in length and width with means 
    (could do random imputation but unnecessary here) 
mean.imp <- function(x) { 
    missing <- is.na(x) 
    n.missing <-sum(missing) 
    x.obs <-a[!missing] 
    imputed <- x 
    imputed[missing] <- mean(x.obs) 
    return (imputed) 
    } 

mean.imp(exampleDF[exampleDF$taxa == "collembola", "length"]) 

n.taxa <- length(unique(exampleDF$taxa)) 
for(i in 1:n.taxa) { 
    mean.imp(exampleDF[exampleDF$taxa == unique(exampleDF$taxa[i]), "length"]) 
} # no way to get back into dataframe in proper places, try plyr? 

một nỗ lực:

imp.mean <- function(x) { 
    a <- mean(x, na.rm = TRUE) 
    return (ifelse (is.na(x) == TRUE , a, x)) 
} # tried but not sure how to use this in ddply 

Diet2 <- ddply(exampleDF, .(taxa), transform, length2 = function(x) { 
    a <- mean(exampleDF$length, na.rm = TRUE) 
    return (ifelse (is.na(exampleDF$length) == TRUE , a, exampleDF$length)) 
    }) 

gợi ý sử dụng Bất kỳ plyr hay không?

+7

Bạn nên xem xét gói * chuột * cho giá trị phân tích. –

+1

gói 'mi' cũng khá tốt. 'Amelia' nhanh hơn nhiều so với' chuột 'hay 'mi', nhưng nó phụ thuộc vào các biến của bạn là đa biến bình thường – richiemorrisroe

Trả lời

37

Không kỹ thuật của riêng tôi tôi thấy nó trên diễn đàn một thời gian trở lại:

dat <- read.table(text = "id taxa  length width 
101 collembola 2.1  0.9 
102 mite  0.9  0.7 
103 mite  1.1  0.8 
104 collembola NA  NA 
105 collembola 1.5  0.5 
106 mite  NA  NA", header=TRUE) 


library(plyr) 
impute.mean <- function(x) replace(x, is.na(x), mean(x, na.rm = TRUE)) 
dat2 <- ddply(dat, ~ taxa, transform, length = impute.mean(length), 
    width = impute.mean(width)) 

dat2[order(dat2$id), ] #plyr orders by group so we have to reorder 

Sửa Một cách tiếp cận phi plyr với một vòng lặp for:

for (i in which(sapply(dat, is.numeric))) { 
    for (j in which(is.na(dat[, i]))) { 
     dat[j, i] <- mean(dat[dat[, "taxa"] == dat[j, "taxa"], i], na.rm = TRUE) 
    } 
} 

Sửa nhiều mặt trăng sau đây là data.table & dplyr ap proach:

data.table

library(data.table) 
setDT(dat) 

dat[, length := impute.mean(length), by = taxa][, 
    width := impute.mean(width), by = taxa] 

dplyr

library(dplyr) 

dat %>% 
    group_by(taxa) %>% 
    mutate(
     length = impute.mean(length), 
     width = impute.mean(width) 
    ) 
+3

@djhocking Cảm ơn Hadley Tôi đã phát hiện ra nơi tôi lấy trộm từ: [(LINK)] (http: // www.mail-archive.com/[email protected]/msg58289.html) –

2

Trước khi trả lời này, tôi muốn nói rằng là một người mới bắt đầu trong R. Do đó, xin vui lòng cho tôi biết nếu bạn cảm thấy câu trả lời của tôi là sai.

Code:

DF[is.na(DF$length), "length"] <- mean(na.omit(telecom_original_1$length)) 

và áp dụng tương tự cho chiều rộng.

DF là tên của data.frame.

Cảm ơn, Parthi

0

Mở rộng trên giải pháp @Tyler Rinker của, giả sử features là các cột để quy cho. Trong trường hợp này là features <- c('length', 'width'). Sau đó, sử dụng data.table giải pháp sẽ trở thành:

library(data.table) 
setDT(dat) 

dat[, (features) := lapply(.SD, impute.mean), by = taxa, .SDcols = features] 
Các vấn đề liên quan