2017-04-15 1 views
-1

Ich habe ein Datenframe mit einer Faktorvariablen und Spalten mit ein paar NA's wie gezeigt.Gruppierung nach einer Variablen, dann Finden des Anteils fehlender Werte für jede Spalte in R

var col1 col2 col3 
C 1 NA 1 
A NA 1 1 
C NA NA NA 
A 1 NA 1 
B NA 1 1 
A 1 1 1 
B 1 NA 1 
B 1 1 1 
C NA NA 1 
B NA 1 1 

Ich bin auf der Suche nach einer Möglichkeit, die Variablen zu gruppieren und den Anteil der fehlenden Werte für jede Spalte erhalten, die durch die Ebene in ‚var‘ gruppiert. Die Ausgabe sollte wie folgt aussehen:

var col1 col2 col3 
A 0.33 0.33 0 
B 0.5 0.25 0 
C 0.66 1.00 0.33 

Jedes Verfahren ist in Ordnung und verschiedene Methoden geschätzt werden würde, aber eine einfache dplyr Methode wäre vorzuziehen. Vielen Dank!

Bearbeiten: Ich bin auf der Suche nach einer Methode, die es mir erlauben würde, dies für mehrere Spalten gleichzeitig zu tun und einen Datenrahmen ähnlich dem oben gezeigten zurückzugeben.

Sagen meine Daten heißt 'df' dann möchte ich tun, um den Anteil der fehlenden für alle Spalten auf einmal zu bekommen, ohne die Namen manuell erneut eingeben zu müssen.

Der folgende Code funktioniert nicht, aber es ist eine allgemeine Vorstellung dessen, was ich erreichen möchte. Vielleicht könnte eine Funktion helfen, aber ich bin mir nicht sicher, wie ich darauf zugehen würde.

df %>% group_by(var) %>% summarise(names(df[,-1]) = sum(is.na(names(df[,-1])))/n())

Antwort

1

Hier ist eine allgemeinere dplyr Lösung mit summarise_each, die eine beliebige Anzahl von Spalten akzeptieren:

df1 <-read.table(text="var col1 col2 col3 
C 1 NA 1 
A NA 1 1 
C NA NA NA 
A 1 NA 1 
B NA 1 1 
A 1 1 1 
B 1 NA 1 
B 1 1 1 
C NA NA 1 
B NA 1 1",header=TRUE, stringsAsFactors=FALSE) 

library(dplyr) 
df1 %>% 
group_by(var) %>% 
summarise_each(funs(sum(is.na(.))/length(.))) 

# A tibble: 3 × 4 
    var  col1  col2  col3 
    <chr>  <dbl>  <dbl>  <dbl> 
1  A 0.3333333 0.3333333 0.0000000 
2  B 0.5000000 0.2500000 0.0000000 
3  C 0.6666667 1.0000000 0.3333333 
1

Sie so etwas wie dies versuchen könnte:

# Create some arbitrary matrix 
rs <- 100 
dat <- data.frame(matrix(1,rs,3)) 

for(i in 1:rs){ 
dat[i,sample(1:3,2,)] <- NA 
} 

dat <- cbind(rep(c("A","B","C"),rs)[1:rs],dat) 

colnames(dat)[1] <- "var" 

# Use the by function with an apply statement 
by(dat[,c("X1","X2","X3")],dat[,"var"],function(x) apply(x,2,function(z){ 
    n <- length(z) 
    miss <- sum(is.na(z)) 
    prop <- miss/n 
    })) 
1

Ihre Daten Rahmen in einem Daten Angenommen data, könnten Sie Folgendes tun:

## Your data: 
data <- structure(list(var = structure(c(3L, 1L, 3L, 1L, 
    2L, 1L, 2L, 2L, 3L, 2L), .Label = c("A", "B", "C"), 
    class = "factor"), col1 = c(1, NA, NA, 1, NA, 1, 1, 1, NA, NA), 
    col2 = c(NA, 1, NA, NA, 1, 1, NA, 1, NA, 1), 
    col3 = c(1, 1, NA, 1, 1, 1, 1, 1, 1, 1)), 
    .Names = c("var", "col1", "col2", "col3"), 
    row.names = c(NA, -10L), class = "data.frame") 

library(dplyr) 
outDf <- data %>% group_by(var) %>% 
    dplyr::summarise(col1 = sum(is.na(col1))/n(), 
        col2 = sum(is.na(col2))/n(), 
        col3 = sum(is.na(col3))/n()) 

outDf 
### A tibble: 3 × 4 
##  var  col1  col2  col3 
## <fctr>  <dbl>  <dbl>  <dbl> 
##1  A 0.3333333 0.3333333 0.0000000 
##2  B 0.5000000 0.2500000 0.0000000 
##3  C 0.6666667 1.0000000 0.3333333 

Edit: Um es auf alle Spalten mit einem Aufruf anzuwenden, können Sie verwenden:

outDf <- data %>% group_by(var) %>% 
    dplyr::summarise_all(function(x) sum(is.na(x))/length(x)) 

outDf 
### A tibble: 3 × 4 
##  var  col1  col2  col3 
## <fctr>  <dbl>  <dbl>  <dbl> 
##1  A 0.3333333 0.3333333 0.0000000 
##2  B 0.5000000 0.2500000 0.0000000 
##3  C 0.6666667 1.0000000 0.3333333 
+0

Wenn ich mehrere Spalten hatte, gibt es einen Weg, ich könnte eine Funktion anwenden, um alle Spalten auf einmal zu senden, ohne es wiederholt eingeben zu müssen – Ricky

1

Wir haben auch diese


mit aggregate von base R

aggregate(.~var, data, FUN = function(x) sum(is.na(x))/length(x), na.action=NULL) 
# var  col1  col2  col3 
#1 A 0.3333333 0.3333333 0.0000000 
#2 B 0.5000000 0.2500000 0.0000000 
#3 C 0.6666667 1.0000000 0.3333333 
tun können Oder mit data.table

library(data.table) 
setDT(data)[, lapply(.SD, function(x) sum(is.na(x))/.N), var] 
Verwandte Themen