2015-03-15 8 views
7

I eine solche Datenrahmen (DF):R rang Werte einer Spalte durch Gruppieren, bedingtes auf eine andere Variable

group col1 col2 
x  a 22  
x  a 23 
x  b 16 
x  b 18 
y  a 11 
y  a 12 
y  a 16 
y  a 45 
y  b 24 

gewünschte Ausgabe ist:

group col1 col2 rank 
x  a 22 1 
x  a 23 2 
x  b 16 0 
x  b 18 0 
y  a 11 1 
y  a 12 2 
y  a 16 3 
y  a 45 4 
y  b 24 0 

nämlich

  • order col2 nach gruppe und col1
  • wenn col1 = "b" dann rank ist 0
  • Rangwerte von col2 vom kleinsten zum größten

Wie kann ich tun, dass R unter Verwendung? Ich werde mich sehr für jede Hilfe freuen. Danke vielmals.

Antwort

8

könnten Sie versuchen,

library(dplyr) 
df %>% 
    group_by(group, col1) %>% 
    mutate(rank=replace(min_rank(col2), col1=='b',0)) 
# group col1 col2 rank 
#1  x a 22 1 
#2  x a 23 2 
#3  x b 16 0 
#4  x b 18 0 
#5  y a 11 1 
#6  y a 12 2 
#7  y a 16 3 
#8  y a 45 4 
#9  y b 24 0 

Wenn Sie Lücken zwischen den Reihen nicht wollen, wenn es Bindungen sind, ersetzen min_rank mit dense_rank

Oder statt replace

res <- df %>% 
      group_by(group, col1) %>% 
      mutate(rank=(col1!='b')*min_rank(col2)) 

as.data.frame(res) #would be `data.frame` 
# group col1 col2 rank 
#1  x a 22 1 
#2  x a 23 2 
#3  x b 16 0 
#4  x b 18 0 
#5  y a 11 1 
#6  y a 12 2 
#7  y a 16 3 
#8  y a 45 4 
#9  y b 24 0 
+0

ich nicht "df" bekommen kann als Datenrahmen. Wie kann ich es als Datenrahmen bekommen? – oercim

+0

@oercim Sie können 'as.data.frame (res)' tun. Aktualisiert den Beitrag – akrun

+0

df ist Datenrahmen, aber die "Rang" -Spalte fehlt – oercim

6

Oder mit data.tablev>= 1.9.5

library(data.table) 
setDT(df)[, rank := frank(col2, ties.method = "dense"), 
      by = .(group, col1)][col1 == "b", rank := 0L][] 

# group col1 col2 rank 
# 1:  x a 22 1 
# 2:  x a 23 2 
# 3:  x b 16 0 
# 4:  x b 18 0 
# 5:  y a 11 1 
# 6:  y a 12 2 
# 7:  y a 16 3 
# 8:  y a 45 4 
# 9:  y b 24 0 

Oder wie @Arun vorgeschlagen, können Sie einen Gruppierungsschritt überspringen, wenn Sie b auf Null ersten

dt[, rank := 0L][col1 != "b", rank := frank(col2, ties.method="dense"), by=group][] 
5

In base R gesetzt wird:

df$rank<-ave(df$col2,df[,1:2],FUN=rank)*(df$col1!="b") 
Verwandte Themen