2017-06-09 6 views
3

Ich habe folgende Datenmenge:Berechnung kategorische Durchschnitt mit gefilterten Daten

A -1 
A 10 
B 8 
D -1 
A 0 
A 4 
B 2 
C 6 

Und ich will Spalte es wie folgt hinzuzufügen:

A -1 4,6 
A 10 4,6 
B 8 5,0 
D -1 5,0 
A 0 4,6 
A 4 4,6 
B 2 5,0 
C 6 6,0 

Was haben hier passiert?

Nun, ich habe Durchschnitt jeder kategorischen Buchstaben Variable berechnet, aber negative Zahlen ignoriert und dies als neue Spalten Wert gegeben.

Wenn nur negative Werte für die Kategorie I angegeben sind, wurde der Wert des Gesamtdurchschnitts angegeben (negative Werte werden ignoriert).

In SQL wäre dies mit gefilterter Gruppenfunktion gefolgt von join geschehen. In Excel wäre dies eine Bedingung vlookup. Wie mache ich das in R?

Edit:

# Create dataset 
category <- c("A","A","B","D","A","A","B","C") 
value <- c(-1,10,8,-1,0,4,2,6) 
dataset <- data.frame(category, value) 

# Calculated means 

fdata <- dataset[dataset[,'value']>-1,] 
aggregate(fdata[,2], list(fdata$category), mean) 

Antwort

4

Wir ave von der Basis R von jedem category gruppiert verwenden können, prüfen wir, ob all die value in einer bestimmten Gruppe kleiner als 0 ist, wenn es dann wählen wir die mean von der gesamten dataset und wenn es nicht so ist, nehmen wir nur die mean der Gruppe.

dataset$mean_column <- with(dataset, ave(value, category, FUN = function(x) 
     ifelse(all(x < 0), mean(value[value >= 0]), mean(x[x >= 0])))) 

dataset 

# category value mean_column 
#1  A -1 4.666667 
#2  A 10 4.666667 
#3  B  8 5.000000 
#4  D -1 5.000000 
#5  A  0 4.666667 
#6  A  4 4.666667 
#7  B  2 5.000000 
#8  C  6 6.000000 
3

Mit dplyr

dataset %>% 
    mutate(
    x = ifelse(value < 0, NA_integer_, value), 
    meanAll = mean(x, na.rm = TRUE)) %>% 
    group_by(category) %>% 
    mutate(meanGroup = mean(x, na.rm = TRUE), 
     meanGroup = ifelse(is.nan(meanGroup), meanAll, meanGroup)) 

# Source: local data frame [8 x 5] 
# Groups: category [4] 
# 
# # A tibble: 8 x 5 
# category value  x meanAll meanGroup 
#  <fctr> <dbl> <dbl> <dbl>  <dbl> 
# 1  A -1 NA  5 4.666667 
# 2  A 10 10  5 4.666667 
# 3  B  8  8  5 5.000000 
# 4  D -1 NA  5 5.000000 
# 5  A  0  0  5 4.666667 
# 6  A  4  4  5 4.666667 
# 7  B  2  2  5 5.000000 
# 8  C  6  6  5 6.000000 
2

Die OP hat geschrieben In SQL diese mit gefilterter Gruppe funcion mit Join gefolgt getan worden wäre. Dieser Ansatz kann mit data.table umgesetzt werden:

library(data.table) 
# filter data and compute group means 
setDT(dataset)[value >= 0, .(grp.mean = mean(value)), category][ 
    # now join with dataset 
    dataset, on = "category"][ 
    # fill empty group means with overall mean of filtered values 
    is.na(grp.mean), grp.mean := dataset[value >= 0, mean(value)]][] 

die zurück

category grp.mean value 
1:  A 4.666667 -1 
2:  A 4.666667 10 
3:  B 5.000000  8 
4:  D 5.000000 -1 
5:  A 4.666667  0 
6:  A 4.666667  4 
7:  B 5.000000  2 
8:  C 6.000000  6 

Hier ist eine kurze Variante, die Zuordnung durch Bezugnahme verwendet und vermeidet die Join-Operation (Ich bin nicht sicher welches ist schneller):

library(data.table) 
# assign by reference of computed group means of filtered values 
setDT(dataset)[, grp.mean := mean(value[value >=0]), category][ 
    # fill empty group means with overall mean of filtered values 
    is.na(grp.mean), grp.mean := dataset[value >= 0, mean(value)]][] 
Verwandte Themen