2015-08-25 13 views
6

Ho un frame di dati che è simile al seguente:valore Assegnare al gruppo in base alla condizione nella colonna

> df = data.frame(group = c(1,1,1,2,2,2,3,3,3), 
       date = c(1,2,3,4,5,6,7,8,9), 
       value = c(3,4,3,4,5,6,6,4,9)) 
> df 
    group date value 
1  1 1  3 
2  1 2  4 
3  1 3  3 
4  2 4  4 
5  2 5  5 
6  2 6  6 
7  3 7  6 
8  3 8  4 
9  3 9  9 

voglio creare una nuova colonna che contiene il valore di data per ogni gruppo che è associato con il valore "4" dalla colonna del valore.

Il seguente frame di dati mostra ciò che spero di ottenere.

group date value newValue 
1  1 1  3  2 
2  1 2  4  2 
3  1 3  3  2 
4  2 4  4  4 
5  2 5  5  4 
6  2 6  6  4 
7  3 7  6  8 
8  3 8  4  8 
9  3 9  9  8 

Come si può vedere, il gruppo 1 ha la newValue "2" perché è la data associata al valore "4". Allo stesso modo, il gruppo due ha newValue 4 e il gruppo tre ha newValue 8.

Suppongo che ci sia un modo semplice per farlo usando ave() o un intervallo di funzioni dplyr/data.table, ma non ho avuto successo con il mio molti tentativi

+0

@DavidArenburg Hai ragione! L'ho appena corretto –

risposta

11

Ecco un rapido data.table uno

library(data.table) 
setDT(df)[, newValue := date[value == 4L], by = group] 
df 
# group date value newValue 
# 1:  1 1  3  2 
# 2:  1 2  4  2 
# 3:  1 3  3  2 
# 4:  2 4  4  4 
# 5:  2 5  5  4 
# 6:  2 6  6  4 
# 7:  3 7  6  8 
# 8:  3 8  4  8 
# 9:  3 9  9  8 

Ecco un simile dplyr versione

library(dplyr) 
df %>% 
    group_by(group) %>% 
    mutate(newValue = date[value == 4L]) 

O una possibile soluzione di base R utilizzando merge dopo il filtraggio dei dati (avrà bisogno di un po ' ridenominazione in seguito)

merge(df, df[df$value == 4, c("group", "date")], by = "group") 
+1

proprio quello di cui avevo bisogno. Grazie! –

+0

@David Arenburg, per favore aiutami con un piccolo ritocco qui, https://stackoverflow.com/questions/47716479/data-frame-modification-in-r –

1

Ecco un'opzione di base R

df$newValue = rep(df$date[which(df$value == 4)], table(df$group)) 

Un'altra alternativa usando lapply

do.call(rbind, lapply(split(df, df$group), 
    function(x){x$newValue = rep(x$date[which(x$value == 4)], 
        each = length(x$group)); x})) 

# group date value newValue 
#1.1  1 1  3  2 
#1.2  1 2  4  2 
#1.3  1 3  3  2 
#2.4  2 4  4  4 
#2.5  2 5  5  4 
#2.6  2 6  6  4 
#3.7  3 7  6  8 
#3.8  3 8  4  8 
#3.9  3 9  9  8 
1

Un'altra base R percorso:

df$newValue <- ave(`names<-`(df$value==4,df$date), df$group, FUN=function(x) as.numeric(names(x)[x])) 
df 
    group date value newValue 
1  1 1  3  2 
2  1 2  4  2 
3  1 3  3  2 
4  2 4  4  4 
5  2 5  5  4 
6  2 6  6  4 
7  3 7  6  8 
8  3 8  4  8 
9  3 9  9  8 
10  3 11  7  8 

ho usato un test su gruppi di lunghezza variabile . Ho assegnato la colonna date come i nomi per l'indice logico di value uguale a 4. Quindi identificare il valore per gruppo.

dati

df = data.frame(group = c(1,1,1,2,2,2,3,3,3,3), 
       date = c(1,2,3,4,5,6,7,8,9,11), 
       value = c(3,4,3,4,5,6,6,4,9,7))