2017-11-17 20 views
8

Tôi có một khung dữ liệu như thế nàycột điền với cột trước nếu NA

df <- data.frame(v1 = 10:14, v2 = c(NA, 1, NA, 3, 6), v3 = c(1, NA, NA, 9, 4)) 

    v1 v2 v3 
1 10 NA 1 
2 11 1 NA 
3 12 NA NA 
4 13 3 9 
5 14 6 4 

bây giờ tôi muốn điền NAS với giá trị của cột trước, vì vậy nó trông như thế này:

v1 v2 v3 
1 10 10 1 
2 11 1 1 
3 12 12 12 
4 13 3 9 
5 14 6 4 

tôi biết làm thế nào để làm điều này bằng tay, như thế này:

df$v2 <- ifelse(is.na(df$v2), df$v1, df$v2) 

làm thế nào tôi có thể tự động này cho một khung dữ liệu đầy đủ với nhiều cột?

Trả lời

8

Bạn có thể làm điều này với fill từ tidyr:

library(dplyr) 
library(tidyr) 

data.frame(t(df)) %>% 
    fill(., names(.)) %>% 
    t() 

Kết quả:

v1 v2 v3 
X1 10 10 1 
X2 11 1 1 
X3 12 12 12 
X4 13 3 9 
X5 14 6 4 

Lưu ý:

Về cơ bản, tôi hoán df, điền mỗi cột xuống, sau đó hoán nó trở lại với định hướng ban đầu

6
for (i in 2:ncol(df)) 
    df[,i] = ifelse(is.na(df[,i]), df[,i-1],df[,i]) 

Điều này sẽ truyền giá trị qua các chuỗi cột NA. Nếu bạn không muốn điều này, chỉ cần đảo ngược thứ tự của các chỉ mục trong khai báo vòng lặp for.

4

Bạn có thể sử dụng apply nhưng lưu ý rằng đầu ra sẽ là một ma trận

t(apply(df, 1, function(x){ 
    replace(x, is.na(x), x[cumsum(!is.na(x))][is.na(x)]) 
})) 
#  v1 v2 v3 
#[1,] 10 10 1 
#[2,] 11 1 1 
#[3,] 12 12 12 
#[4,] 13 3 9 
#[5,] 14 6 4 
6

Một tùy chọn sử dụng Reduce với ifelse:

df[] <- Reduce(function(x, y) ifelse(is.na(y), x, y), df, accumulate = TRUE) 

df 
# v1 v2 v3 
#1 10 10 1 
#2 11 1 1 
#3 12 12 12 
#4 13 3 9 
#5 14 6 4 
4

Bằng cách sử dụng zoona.locf

data.frame(t(apply(df,1,function(x) na.locf(x)))) 
    v1 v2 v3 
1 10 10 1 
2 11 1 1 
3 12 12 12 
4 13 3 9 
5 14 6 4 
+1

'na.locf' có thể được áp dụng cho toàn bộ khung dữ liệu cùng một lúc để 'na.locf (df, na.rm = FALSE)' sẽ hoạt động. (Trong trường hợp cụ thể này, 'na.rm = FALSE' không làm gì cả, nhưng nếu các hàng đầu là tất cả các NA thì nó sẽ giữ chúng.) –

+0

@ G.Gothendieck tìm hiểu nó, Cảm ơn :-) – Wen

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