2013-08-13 15 views
10

Podczas korzystania z apply na data.frame, argumenty są (niejawnie) konwertowane na znak. Przykład:Jak uniknąć niejawnej konwersji znaków podczas używania Zastosuj na ramce danych

df <- data.frame(v=1:10, t=1:10) 
df <- transform(df, t2 = as.POSIXlt(t, origin = "2013-08-13")) 
class(df$t2[1]) 
## [1] "POSIXct" "POSIXt" (correct) 

ale:

apply(df, 1, function(y) class(y["t2"])) 
## [1] "character" "character" "character" "character" "character" "character" 
## [7] "character" "character" "character" "character" 

Czy istnieje jakiś sposób, aby uniknąć tej konwersji? Czy zawsze muszę przeprowadzić konwersję z powrotem przez as.POSIXlt(y["t2"])?

edit
Moja df ma 2 znaczniki czasu (powiedzmy, T2 i T3) i niektóre inne pola (powiedzmy, v1, v2). Dla każdego wiersza z podanym t2, chcę znaleźć k (np. 3) wierszy z t3 najbliższym, ale niższym niż t2 (i tym samym v1), i zwrócić statystyki powyżej v2 z tych wierszy (np. Średnia). Napisałem funkcję f (t2, v1, df) i po prostu chciałem ją zastosować we wszystkich wierszach używając apply(df, 1, function(x) f(y["t2"], y["v1"], df). Czy istnieje lepszy sposób na robienie takich rzeczy w R?

+5

Prawdziwą odpowiedzią jest to, że nie powinieneś używać 'apply' na ramce danych. Co próbujesz zrobić? – joran

+7

Konwersja * występuje, ponieważ twoje 'dane.frame' jest wymuszane na' macierz'. –

+0

Według twoich edycji naprawdę masz dwa różne pytania (IMO). Powiedziałbym, że zadaj drugie pytanie (Twoja edycja) z odpowiednim zestawem danych, próbą i pożądanym wynikiem. –

Odpowiedz

4

Niech owinąć się wiele komentarzy do wyjaśnienia.

  1. wykorzystanie apply konwertuje data.frame do matrix. Ten oznacza, że ​​zostanie użyta klasa najmniej restrykcyjna. Najmniej restrykcyjne w tym przypadku jest .
  2. Podajesz argument o 1 do o numerze MARGIN. Odnosi się to kolejno do i jeszcze ciężej, bo teraz razem mieszacie klasy . W tym scenariuszu używasz apply Zaprojektowany dla macierzy i data.frames na wektorze. To nie jest właściwe narzędzie do pracy.
  3. w tys przypadku użyłbym lapply lub sapply jak wskazuje RMK się porwać klasy że kolumna pojedynczy t2, jak widać poniżej:

Kod:

df <- data.frame(v=1:10, t=1:10) 
df <- transform(df, t2 = as.POSIXlt(t, origin = "2013-08-13")) 

sapply(df[, "t2"], class) 
lapply(df[, "t2"], class) 

## [[1]] 
## [1] "POSIXct" "POSIXt" 
## 
## [[2]] 
## [1] "POSIXct" "POSIXt" 
## 
## [[3]] 
## [1] "POSIXct" "POSIXt" 
## 
## . 
## . 
## . 
## 
## [[9]] 
## [1] "POSIXct" "POSIXt" 
## 
## [[10]] 
## [1] "POSIXct" "POSIXt" 

Ogólnie wybrać rodzina apply, która pasuje do pracy. Często osobiście używam pętli lapply lub for, aby działać na konkretnych kolumnach lub podzbioru kolumn, które chcę, używając indeksowania ([, ]), a następnie postępować zgodnie z apply. Odpowiedź na ten problem sprowadza się do określenia, co chcesz osiągnąć, zadając najodpowiedniejsze narzędzie i kontynuując od tego.

Mogę zaoferować ten blog post jako doskonały samouczek na temat różnych funkcji różnych apply.

+1

Post na blogu jest doskonały, ale myślę, że to nie rozwiąże mojego problemu. "by" powinno być używane dla ramek danych, ale potrzebuję czegoś więcej niż tylko grupowania przez v1. –

0

Spróbuj:

sapply(df, function(y) class(y["t2"])) 

$v 
[1] "integer" 

$t 
[1] "integer" 

$t2 
[1] "POSIXct" "POSIXt" 
+1

Dzięki, ale muszę zastosować moją funkcję do każdego wiersza ramki danych. W rezultacie chcę mieć tyle wierszy, ile w oryginalnej ramce danych. –