Mam dużą tabelę danych z wieloma brakującymi wartościami rozrzuconymi po ~ 200 tys. Wierszach i 200 kolumnach. Chciałbym ponownie zakodować te wartości NA zera tak efektywnie, jak to możliwe.
Widzę dwie opcje:
1: Konwertuj na ramkę danych i użyj czegoś takiego
2: Jakieś fajne polecenie ustawienia podrzędnego danych. Tabeli
Będę zadowolony z dość wydajnego rozwiązania typu 1. Konwersja do pliku data.frame, a następnie z powrotem do pliku data.table nie zajmie zbyt dużo czasu.
data.table
adata.frame
?data.table
Jestdata.frame
. Każda operacja data.frame po prostu zadziała.data.table
, podając numer kolumny. więcDT[,3]
nie da trzeciej kolumny. Myślę, że to sprawia, że rozwiązanie zaproponowane w linku jest nieopłacalne. jestem pewien, że istnieje eleganckie podejście z użyciem jakiejśdata.table
magii!DT[, 3, with=FALSE]
zwraca trzecią kolumnę.mydf[is.na(mydf) == TRUE]
wykonuje pracę na ramkach danych, podczas gdymydt[is.na(mydt) == TRUE]
daje mi coś dziwnego, nawet jeśli używamwith=FALSE
Odpowiedzi:
Oto rozwiązanie przy użyciu data.table „s
:=
operatora, w oparciu o Andrie i odpowiedzi Ramnath użytkownika.Zauważ, że f_dowle zaktualizował dt1 przez odniesienie. Jeśli wymagana jest kopia lokalna, konieczne jest jawne wywołanie
copy
funkcji, aby utworzyć lokalną kopię całego zestawu danych. data.table użytkownikasetkey
,key<-
a:=
nie kopiowanie przy zapisie.Następnie zobaczmy, gdzie f_dowle spędza czas.
Tam skupiłbym się na
na.replace
iis.na
, gdzie jest kilka kopii wektorowych i skanów wektorowych. Można je dość łatwo wyeliminować, pisząc małą funkcję na.replace w C, która aktualizuje sięNA
przez odniesienie w wektorze. Myślę, że to przynajmniej o połowę skróciłoby te 20 sekund. Czy taka funkcja istnieje w jakimkolwiek pakiecie języka R?Przyczyną
f_andrie
niepowodzenia może być to, że kopiuje on całośćdt1
lub tworzydt1
kilka razy logiczną macierz tak dużą, jak całość . Pozostałe 2 metody działają na jednej kolumnie naraz (chociaż przyjrzałem się im tylko krótkoNAToUnknown
).EDYCJA (bardziej eleganckie rozwiązanie, o które prosił Ramnath w komentarzach):
Żałuję, że nie zrobiłem tego w ten sposób na początku!
EDIT2 (ponad 1 rok później, teraz)
Jest też
set()
. Może to być szybsze, jeśli w pętli jest dużo kolumn, ponieważ pozwala to uniknąć (małego) narzutu wywołania[,:=,]
w pętli.set
jest zapętlony:=
. Zobacz?set
.źródło
eval(parse)...
rzeczy. w szerszym ujęciu, myślę, że warto byłoby mieć operacje, które działają na wszystkich elementachdata.table
.data.table
odpowiednim sposobem, aby to zrobić. Dzięki!DT
kolumny typulogical
, w przeciwieństwie docreate_dt()
przykładu dla tego testu. Zmień czwarty argumentset()
wywołania (który jest0
w twoim przykładzie i wpisz double w R) naFALSE
i powinien działać bez ostrzeżenia.seq_along(DT)
też wolę . Ale wtedy czytelnik musi wiedzieć, żeseq_along
będzie to wzdłuż kolumn, a nie wzdłuż rzędów.seq_len(col(DT))
z tego powodu trochę bardziej jednoznaczne.Oto najprostszy, jaki mogłem wymyślić:
dt[is.na(dt)] <- 0
Jest wydajna i nie wymaga pisania funkcji ani innego kodu kleju.
źródło
[.data.table
(dt, is.na (dt)): i jest nieprawidłowym typem (macierz). Być może w przyszłości macierz dwukolumnowa zwróci listę elementów DT (w duchu A [B] w FAQ 2.14). Daj znać datatable-help, jeśli chcesz, lub dodaj swoje komentarze do FR # 657. >set
Dedykowane funkcje (
nafill
isetnafill
) do tego celu dostępne są wdata.table
pakiecie (wersja> = 1.12.4):Przetwarza kolumny równolegle, więc dobrze odpowiada wcześniej opublikowanym testom porównawczym, poniżej jego czasów w porównaniu z najszybszym do tej pory podejściem, a także skaluje się w górę, używając maszyny 40-rdzeniowej.
źródło
Tylko w celach informacyjnych, wolniej w porównaniu do gdata lub data.matrix, ale używa tylko pakietu data.table i radzi sobie z wpisami nienumerycznymi.
źródło
ifelse
i zaktualizować przez odniesienie, wykonującDT[, names(DT) := lapply(.SD, function(x) {x[is.na(x)] <- "0" ; x})]
. I wątpię, że będzie to wolniejsze niż odpowiedzi, o których wspomniałaś.Oto rozwiązanie używane
NAToUnknown
wgdata
pakiecie. Użyłem rozwiązania Andrie'ego, aby stworzyć ogromną tabelę danych, a także uwzględniłem porównania czasu z rozwiązaniem Andrie.źródło
user
czasem, ale naprawdę dużą różnicą welapsed
czasie.rbenchmark
do testów porównawczych rozwiązań przy użyciu większej liczby replikacji, ale wystąpił błąd braku pamięci, prawdopodobnie ze względu na rozmiar ramki danych. jeśli możesz uruchomićbenchmark
oba te rozwiązania z wieloma replikacjami, te wyniki byłyby interesujące, ponieważ nie jestem do końca pewien, dlaczego otrzymuję 3ncol=5
mnie (powinny zająć znacznie dłużej) z powodu błędu wcreate_dt
.Ze względu na kompletność innym sposobem zastąpienia NA na 0 jest użycie
Aby porównać wyniki i czasy, zastosowałem wszystkie wspomniane dotychczas podejścia.
Tak więc nowe podejście jest nieco wolniejsze,
f_dowle3
ale szybsze niż wszystkie inne podejścia. Ale szczerze mówiąc, jest to sprzeczne z moją intuicją dotyczącą składni data.table i nie mam pojęcia, dlaczego to działa. Czy ktoś może mnie oświecić?źródło
Rozumiem, że sekret szybkich operacji w R polega na wykorzystaniu wektorów (lub tablic, które są wektorami pod maską).
W tym rozwiązaniu używam a
data.matrix
który jest a,array
ale zachowuję się trochę jak adata.frame
. Ponieważ jest to tablica, możesz użyć bardzo prostego podstawienia wektora, aby zastąpićNA
s:Mała funkcja pomocnicza do usuwania
NA
s. Istotą jest pojedyncza linia kodu. Robię to tylko po to, aby zmierzyć czas wykonania.Mała funkcja pomocnicza do tworzenia
data.table
rozmiaru o podanym rozmiarze.Demonstracja na małej próbce:
źródło
remove_na
. Ten czas 21,57s obejmujecreate_dt
(w tymrunif
isample
) wraz zremove_na
. Jest jakaś szansa, że mógłbyś edytować, aby podzielić 2 razy?create_dt
? Wydaje się zawsze stworzyć data.table 5 kolumny niezależnie odncol
przekazany w.Aby uogólnić na wiele kolumn, możesz użyć tego podejścia (używając poprzednich przykładowych danych, ale dodając kolumnę):
Nie testowałem jednak szybkości
źródło
źródło
Korzystając z
fifelse
funkcji z najnowszychdata.table
wersji 1.12.6 jest to nawet 10 razy szybsze niżNAToUnknown
wgdata
pakiecie:źródło
f_dowle3
nadal będzie szybszy: stackoverflow.com/a/7249454/345660