2016-12-29 7 views
2

Den Versuch, jemandes Frage auf der ggplot2 Mailing-Liste zu beantworten, und ich kann es nicht herausgefunden: https://groups.google.com/forum/#!topic/ggplot2/YgCqQX8JbPMverschiedene Startparameter Bewerben purrr :: map innerhalb dplyr mit nach Modell :: mutieren

OP will verschiedenen Start anwenden Parameter zu Teilmengen seiner Daten für das nls-Modell. Meine Gedanken waren, dass er dplyr lesen und schnurren sollte, aber nach ein paar Stunden, in denen ich mich selbst versuchte, habe ich eine Wand getroffen. Unsicher, ob es ein Fehler oder meine mangelnde Erfahrung mit purrr ist.

library(tidyverse) 

# input dataset 
df <- data.frame(Group = c(rep("A", 7), rep("B", 7), rep("C", 7)), 
       Time = c(rep(c(1:7), 3)), 
       Result = c(100, 96.9, 85.1, 62.0, 30.7, 15.2, 9.6, 
          10.2, 14.8, 32.26, 45.85, 56.25, 70.1, 100, 
          100, 55.61, 3.26, -4.77, -7.21, -3.2, -5.6)) 

# nest the datasets for computing models 
df_p <- 
df %>% 
group_by(Group) %>% 
nest 

# add model parameters as rows/columns 
df_p$starta = c(-3, 4,-3) 
df_p$startb = c(85, 85, 85) 
df_p$startc = c(4, 4, 4) 
df_p$startd = c(10,10,10) 

# compute models using nls 
df_p %>% 
mutate(model2 = map(data, ~nls(Result ~ a+(b-a)/(1+(Time/c)^d), data = ., start = c(a = starta, b = startb, c = startc, d = startd))) 
     ) 

#Error in mutate_impl(.data, dots) : 
# parameters without starting value in 'data': a, b, d 

Fühlt sich zu diesem Fehler verwendet, aber dies für eine Weile wurde nun behoben ... https://github.com/hadley/dplyr/issues/1447

Von dem, was ich sagen kann, es ist für die Variablen im Rahmen des verschachtelten tibble suchen, aber ich möchte, dass es im Rahmen des Mutate-Aufrufs ist. Ich weiß nicht, ob es einen Weg gibt.

Antwort

6

Das Beispiel Daten sind knifflig, weil Gruppe B im Prinzip Zeit in umgekehrter Richtung hat. Gute Startwerte dafür zu finden, ist nicht mein Problem. Also habe ich neue Daten für die Gruppe B erstellt. Hier erfahren Sie, wie Sie einen Datenrahmen einrichten, um nls() innerhalb von map2() zu übernehmen.


library(tidyverse) 

df <- data.frame(Group = c(rep("A", 7), rep("B", 7), rep("C", 7)), 
       Time = c(rep(c(1:7), 3)), 
       Result = c(100, 96.9, 85.1, 62.0, 30.7, 15.2, 9.6, 
          ## I replaced these values!! 
          ## Group B initial values are NOT MY PROBLEM 
          105, 90, 82, 55, 40, 23, 7, 
          100, 55.61, 3.26, -4.77, -7.21, -3.2, -5.6)) 

## ggplot(df, aes(x = Time, y = Result, group = Group)) + geom_line() 

df_p <- 
    df %>% 
    group_by(Group) %>% 
    nest() %>% 
    ## init vals are all the same, but this shows how to make them different 
    mutate(start = list(
    list(a = -3, b = 85, c = 4, d = 10), 
    list(a = -3, b = 85, c = 4, d = 10), 
    list(a = -3, b = 85, c = 4, d = 10) 
) 

) 

df_p %>% 
    mutate(model2 = map2(data, start, 
         ~ nls(Result ~ a+(b-a)/(1+(Time/c)^d), 
          data = .x, start = .y))) 
#> # A tibble: 3 × 4 
#> Group    data  start model2 
#> <fctr>   <list>  <list> <list> 
#> 1  A <tibble [7 × 2]> <list [4]> <S3: nls> 
#> 2  B <tibble [7 × 2]> <list [4]> <S3: nls> 
#> 3  C <tibble [7 × 2]> <list [4]> <S3: nls> 
+0

der Tat nicht Ihr Problem, nicht meins mit den Parametern selbst. Eine Frage ist, wie Sie die Listenspalten als .x und .y referenzieren. Woher weißt du das zu tun? Warum nicht .data und .start? – bhive01

+1

Die Platzhalter, wenn Sie die Formelverknüpfung von purrr zum Definieren der zuzuweisenden Funktion verwenden, sind immer '.x' (' map _ *() 'variants) oder' .x' und '.y' (' map2 _ *() ' B. in der Hilfedatei 'purrr :: map()' – jennybryan

+1

Wenn Sie 'pmap()' verwenden, können Sie sich in Ihrer benutzerdefinierten Funktion auf Argumentnamen verlassen. Die Formelverknüpfung ist in diesem Fall nicht mehr relevant Sie könnten 'myfun <- function (.data, .start) nls (Ergebnis ~ a + (ba)/(1+ (Zeit/c)^d), data = .data, start = .start) definieren Stellen Sie sicher, dass Sie genau diese Variablennamen und nur die Variablen in dem Datenrahmen verwenden, den Sie als primäre Eingabe für 'pmap (wählen Sie (df, .data, .start), myfun)' planen. – jennybryan

2

Es ist nicht möglich, eine Reihe von Parametern zu finden, um die von Ihnen eingerichteten Modelle zu erstellen, aber ich denke, dass Sie das tun können, wenn Sie den Modellanpassungsprozess einrichten; Grundsätzlich können Sie alle Parameter starta, startb .. etc in die Daten sowie die Result und Time Spalten, und dann können Sie die Parameter mit .$, Hinweis in diesem Fall müssen Sie die Funktion, um einen Wert auszuwählen, wie der Wert gesendet wurde beim Entknoten. Mit einer einfachen Modellformel, a + b*Time, produziert sie die Modelle in der model2 Spalte, können Sie diesen Weg folgen und die Anfangsparameter optimieren zu nls geleitet, um eine kompliziertere Formel zu passen, wie Sie angegeben haben:

library(tidyverse) 

df_p %>% unnest %>% group_by(Group) %>% nest %>% 
     mutate(model2 = map(data, ~nls(Result ~ a + b*Time, data = ., 
             start = c(a = unique(.$starta), 
                b = unique(.$startb)) 
             ) 
          ) 
       ) 

# A tibble: 3 × 3 
# Group    data model2 
# <fctr>   <list> <list> 
#1  A <tibble [7 × 6]> <S3: nls> 
#2  B <tibble [7 × 6]> <S3: nls> 
#3  C <tibble [7 × 6]> <S3: nls> 
Verwandte Themen