2016-03-30 20 views
0

Ich würde gerne die Prägnanz von magritr, dplyr und möglicherweise purrr verwenden, um einen großen Datenrahmen (mit vielen Variablen verschiedener Typen) durch eine Variable x aufzuteilen Anwendung verschiedener Funktionen bedingt durch x auf jede Gruppe und Zeile innerhalb einer Gruppe auf eine zweite Variable y.Bedingte Anwendung von Funktionen auf gruppierte Datenframes in R mit magrittr, dplyr und purrr

Nehmen Sie den Datenrahmen df <- data.frame(a, b, x, c, d, y), wo x Faktoren sind (foo, bar) und y sind Zahlen. Ich kann tun, was ich so unelegant mit einem unpiped Workflow beschrieben:

df$y[df$x == "foo"] %<>% subtract(min(.)) 
df$y[df$x == "bar"] %<>% add(max(df$y[df$x == "foo"])) 

Ich mag würde dies mit dplyr neu zu schreiben und es zu einem langen Rohr hinzufügen für df, aber all meine Versuche zu kombinieren mutate, sapply und do Habe versagt; ebenso wie Versuche, purrr mit anonymen Funktionen zu integrieren, by_slice und dmap.

Vielen Dank im Voraus für den Rat.

+1

, wenn Sie, ich könnte einen Beispieldatensatz liefern könnten versuchen, Antworten. – timelyportfolio

Antwort

1

Dies ist mehr dplyr als magrittr, aber ich denke, es ist auch lesbarer. Ich bin etwas unbehaglich mit %<>%, weil es die lineare Struktur von Operationen stört und den Code schwerer lesbar macht. Also benutze ich einfach %>% hier.

Ein Beispiel Datenrahmen, die Ihre Beschreibung paßt:

df <- data.frame(a = 'a', 
       b = 'b', 
       x = c("foo", "bar") , 
       c = 'c', 
       d = 'd', 
       y = 1:6) 
df 
    a b x c d y 
1 a b foo c d 1 
2 a b bar c d 2 
3 a b foo c d 3 
4 a b bar c d 4 
5 a b foo c d 5 
6 a b bar c d 6 

Ihr Code:

library(dplyr) 
library(magrittr) 
df$y[df$x == "foo"] %<>% subtract(min(.)) 

df 
    a b x c d y 
1 a b foo c d 0 
2 a b bar c d 2 
3 a b foo c d 2 
4 a b bar c d 4 
5 a b foo c d 4 
6 a b bar c d 6 

df$y[df$x == "bar"] %<>% add(max(df$y[df$x == "foo"])) 

df 
    a b x c d y 
1 a b foo c d 0 
2 a b bar c d 6 
3 a b foo c d 2 
4 a b bar c d 8 
5 a b foo c d 4 
6 a b bar c d 10 

A dplyr Lösung:

df %>% 
    mutate(y = ifelse(x == "foo", y - min(y), y)) %>% 
    mutate(y = ifelse(x == "bar", y + max(y[x == 'foo']), y)) 

    a b x c d y 
1 a b foo c d 0 
2 a b bar c d 6 
3 a b foo c d 2 
4 a b bar c d 8 
5 a b foo c d 4 
6 a b bar c d 10