2014-11-05 11 views
11

Mam wiele dobrych opinii na temat question I recently asked i zostałem poproszony o użycie dplyr do transformacji niektórych danych. Mam problem z lm() i próbuję znaleźć nachylenie z tych przekształconych danych i myślałem, że otworzę nowe pytanie.Model liniowy i dplyr - lepsze rozwiązanie?

pierwsze mam dane, które wygląda następująco:

Var1 Var2 Var3 Time   Temp 
a  w  j  9/9/2014  20 
a  w  j  9/9/2014  15 
a  w  k  9/20/2014  10 
a  w  j  9/10/2014  0 
b  x  L  9/12/2014  30 
b  x  L  9/12/2014  10 
b  y  k  9/13/2014  20 
b  y  k  9/13/2014  15 
c  z  j  9/14/2014  20 
c  z  j  9/14/2014  10 
c  z  k  9/14/2014  11 
c  w  l  9/10/2014  45 
a  d  j  9/22/2014  20 
a  d  k  9/15/2014  4 
a  d  l  9/15/2014  23 
a  d  k  9/15/2014  11 

i chcę go w postaci tego (wartości dla Slope i Pearson symulowane na ilustracji):

V1 V2 V3 Slope Pearson 
a w j -3  -0.9 
a w k 2  0 
a d j 1.5  0.6 
a d k 0  0.5 
a d l -0.5 -0.6 
b x L 12  0.7 
b y k 4  0.6 
c z j -1  -0.5 
c z k -3  -0.4 
c w l -10  -0.9 

Nachylenie bycia nachylenie liniowe najmniejszych kwadratów. Teoretycznie skrypt wyglądałby tak:

library(dplyr) 

data <- read.table("clipboard",sep="\t",quote="",header=T) 

newdata = summarise(group_by(data 
           ,Var1 
           ,Var2 
           ,Var3        
          ) 
        ,Slope = lm(Temp ~ Time)$coeff[2]     
        ,Pearson = cor(Time, Temp, method="pearson") 
        ) 

Ale R zgłasza błąd, ponieważ nie może znaleźć czasu ani temp. Może on uruchamiać lm(data$Temp ~ data$Time)$coeff[2], ale zwraca nachylenie dla całego zestawu danych, a nie dla podsekcji, której szukam. Wydaje się, że cor() działa poprawnie w sekcji group_by, więc czy istnieje specyficzna składnia, którą muszę przekazać do lm(), aby uruchomić ją w podobny sposób, lub użyć zupełnie innej funkcji, aby uzyskać nachylenie przekazane z podzbioru?

+0

Jeden z tutejszych problemów jest to, że nie masz wystarczająco dużo różnych wartości podczas grupowania przez zm1 i VAR2 i VAR3, regresja liniowa, więc nie jest możliwe –

+0

Innym problemem jest to, co dokładnie korelacja próbujesz sprawdzić między 'Time' i' Temp'? 'Czas' to data, korelacja Pearsona wymaga dwóch wektorów liczbowych. –

+1

Możesz rzucić okiem na przykłady'? Do', gdzie uruchamiają modele 'lm' na zgrupowanych danych i wyodrębniają statystyki z każdego modelu. – Henrik

Odpowiedz

19

Masz kilka problemów tutaj.

  1. Jeśli wy grupować dane o 3 zmiennych (lub nawet 2) nie masz wystarczającej liczby różnych wartości w celu uruchomienia modelu regresji liniowej
  2. Pearson wymaga dwóch wartości liczbowych, a Time jest czynnikiem, który konwersja do liczbowe nie będzie sensu
  3. trzecią kwestią jest to, że trzeba będzie użyć do aby uruchomić model liniowy

Oto ilustracja do grupowania tylko na V1

data %>% 
    group_by(Var1) %>% # You can add here additional grouping variables if your real data set enables it 
    do(mod = lm(Temp ~ Time, data = .)) %>% 
    mutate(Slope = summary(mod)$coeff[2]) %>% 
    select(-mod) 
# Source: local data frame [3 x 2] 
# Groups: <by row> 
# 
# Var1  Slope 
# 1 a 12.66667 
# 2 b -2.50000 
# 3 c -31.33333 

Jeśli masz dwie zmienne numeryczne można użyć do w celu obliczenia korelacji też, na przykład (będę tworzyć jakieś sztuczne zmienne numeryczne dla ilustracji)

data %>% 
    mutate(test1 = sample(1:3, n(), replace = TRUE), # Creating some numeric variables 
     test2 = sample(1:3, n(), replace = TRUE)) %>% 
    group_by(Var1) %>% 
    do(mod = lm(Temp ~ Time, data = .), 
    mod2 = cor(.$test1, .$test2, method = "pearson")) %>% 
    mutate(Slope = summary(mod)$coeff[2], 
     Pearson = mod2[1]) %>% 
    select(-mod, -mod2) 


# Source: local data frame [3 x 3] 
# Groups: <by row> 
# 
# Var1  Slope  Pearson 
# 1 a 12.66667 0.25264558 
# 2 b -2.50000 -0.09090909 
# 3 c -31.33333 0.30151134 

Rozwiązanie premiowe: możesz to zrobić całkiem sprawnie/łatwo za pomocą pakietu data.table również

library(data.table) 
setDT(data)[, list(Slope = summary(lm(Temp ~ Time))$coeff[2]), Var1] 
# Var1  Slope 
# 1: a 12.66667 
# 2: b -2.50000 
# 3: c -31.33333 

Lub jeśli chcemy stworzyć pewne zmienne fikcyjne zbyt

library(data.table) 
setDT(data)[, `:=`(test1 = sample(1:3, .N, replace = TRUE), 
        test2 = sample(1:3, .N, replace = TRUE))][, 
        list(Slope = summary(lm(Temp ~ Time))$coeff[2], 
         Pearson = cor(test1, test2, method = "pearson")), Var1] 
# Var1  Slope  Pearson 
# 1: a 12.66667 -0.02159168 
# 2: b -2.50000 -0.81649658 
# 3: c -31.33333 -1.00000000 
+1

Może użyć' transmute() 'lub' summary() 'zamiast' mutate() '+' select() '? – hadley

+0

@hadley, myślałem o zrobieniu tego również, 'summary 'i' transmute' opuszczają 'Var1' z wyjścia –

+2

Nie używaj' lm', jeśli chcesz efektywnie uzyskać nachylenie. Użyj 'lsfit'. – Roland

Powiązane problemy