2017-10-10 1 views
2

Ich möchte eine sumif äquivalent Operation in R durchführen.Fall wenn in Gruppe von in R

Immer wenn die ID und der Typ übereinstimmen und das Flag 0 ist, möchte ich einen Prozentsatz berechnen (im folgenden Beispiel ist es (1/(9 + 30826)), sonst möchte ich es als 0% behalten (wenn gibt es keine 0-Flag)

Hier ist das Beispiel:

ID Type Flag Value1 Value2 
1 Apple 0  1  9   
1 Apple 1  29312 30826 
1 Orange 1  2222  3423 
2 Orange 1  24566 32234 

ich möchte folgendes Ergebnis:

ID Type Value1 Value2 Result 
1 Apple 29313 30835 0.0032% 
1 Orange 2222 3423 0% 
2 Orange 24566 32234 0% 

Antwort

1

Sie ave() verwenden können:

d <- read.table(header=TRUE, text="ID Type Flag Value1 Value2 
1 Apple 0  1  9   
1 Apple 1  29312 30826 
1 Orange 1  2222  3423 
2 Orange 1  24566 32234") 

d$Result <- ave(ifelse(d$Flag==0, d$Value1, 0), d$ID, d$Type, FUN=sum)/ave(d$Value2, d$ID, d$Type, FUN=sum) 
d$Value1 <- ave(d$Value1, d$ID, d$Type, FUN=sum) 
d$Value2 <- ave(d$Value2, d$ID, d$Type, FUN=sum) 
dResult <- d[d$Flag==1,] 
dResult 
# > dResult 
# ID Type Flag Value1 Value2  Result 
# 2 1 Apple 1 29313 30835 3.243068e-05 
# 3 1 Orange 1 2222 3423 0.000000e+00 
# 4 2 Orange 1 24566 32234 0.000000e+00 

Für die $Result in [%] können Sie tun d$Result <- 100*ave(...)

+0

Hey Danke! Aber Wert 2 in der ersten Zeile sollte 30835 sein! – AB6

1

umrechnen data.frame zu 'data.table' (setDT(df1)), gruppiert nach 'ID', 'Typ', wenn die Anzahl der Beobachtungen ist größer als 1, mache die Division wie im Post des OP gezeigt oder gebe 0 zurück. Entferne die 'Flag' Spalte, dann erhält man die sum von 'Value1' und 'Value2' gruppiert nach 'ID' und 'Type' und nehmen Sie die unique

library(data.table) 
setDT(df1)[, Result := if(.N >1) round(100*Value1[1]/(Value2[1]+Value2[2]), 3) 
             else 0, .(ID, Type)] 
df2 <- df1[, -3, with = FALSE] 
df2[, (3:4) := lapply(.SD, sum), .SDcols = Value1:Value2, .(ID, Type)] 
unique(df2) 
# ID Type Value1 Value2 Result 
#1: 1 Apple 29313 30835 0.003 
#2: 1 Orange 2222 3423 0.000 
#3: 2 Orange 24566 32234 0.000 

Oder wir können die tidyverse in einem einzigen Strom verwenden. Nach Gruppierung von 'ID', 'Typ', erstellen Sie das 'Ergebnis' Spalte, gefolgt von der sum von ‚Value bekommen columns with mutate_at , remove the 'Flag' and get the distinct` Reihen

library(dplyr) 
df1 %>% 
    group_by(ID, Type) %>% 
    mutate(Result = round(100*if(n()==2) first(Value1)/(first(Value2)+last(Value2)) 
          else 0, 3)) %>% 
    mutate_at(vars(matches('Value')), sum) %>% 
    select(-Flag) %>% 
    distinct 
# A tibble: 3 x 5 
# Groups: ID, Type [3] 
#  ID Type Value1 Value2 Result 
# <int> <chr> <int> <int> <dbl> 
#1  1 Apple 29313 30835 0.003 
#2  1 Orange 2222 3423 0.000 
#3  2 Orange 24566 32234 0.000