Jaka jest najbardziej przydatna sztuczka R? [Zamknięte]
88
Aby podzielić się kolejnymi wskazówkami i trikami dotyczącymi języka R , jaka jest Twoja najbardziej przydatna funkcja lub sztuczka? Sprytna wektoryzacja? Wejście / wyjście danych? Wizualizacja i grafika? Analiza statystyczna? Funkcje specjalne? Samo środowisko interaktywne?
Jedna pozycja na post i zobaczymy, czy wygramy w drodze głosów.
[Edit 25-Aug 2008]: Tak więc po tygodniu wydaje się, że str()ankietę wygrał prosty . Ponieważ lubię to polecać, jest to łatwa do zaakceptowania odpowiedź.
Znów zastraszanie przez CW. Zobaczę twoją meta-SO i wychowam
ars
13
@ars: to pytanie, na które nie ma jednoznacznej odpowiedzi . Ergo sprawi, że będzie CW.
dmckee --- kociak byłego moderatora
2
@JD Długi zabawny komentarz. niestety został schowany za fałdą. Mam na myśli, że odpowiadanie na trudne pytania R nie opłaca się zbytnio. Więc jest dla mnie w porządku, jeśli faceci, którzy zadają fajne pytania, które umieszczają R na mapie, w końcu dostaną trochę uznania. Poza tym jest to z pewnością bardziej przydatne dla użytkowników języka R niż pytanie o to, jakie jest twoje ulubione pytanie dotyczące sztuczki C dla programistów C ...
Bardzo przydatne może być publikowanie łatwo odtwarzalnych fragmentów danych, gdy prosisz o pomoc lub edytujesz lub zmieniasz kolejność poziomów współczynnika.
head () i tail (), aby uzyskać pierwszą i ostatnią część ramki danych, wektora, macierzy, funkcji itp. Szczególnie w przypadku dużych ramek danych jest to szybki sposób sprawdzenia, czy został załadowany prawidłowo.
Jedna fajna funkcja: odczyt danych wykorzystuje połączenia, które mogą być plikami lokalnymi, plikami zdalnymi dostępnymi przez http, potokami z innych programów lub więcej.
Jako prosty przykład rozważmy ten dostęp dla N = 10 losowych liczb całkowitych od min = 100 do max = 200 z random.org (który dostarcza prawdziwe liczby losowe oparte na szumie atmosferycznym, a nie na generatorze liczb pseudolosowych):
R> site <- "http://random.org/integers/"# base URL
R> query <- "num=10&min=100&max=200&col=2&base=10&format=plain&rnd=new"
R> txt <- paste(site, query, sep="?") # concat url and query string
R> nums <- read.table(file=txt) # and read the data
R> nums # and show it
V1 V2
11651432107118310313241911005138185
R>
Tak na marginesie, losowo pakiet zawiera kilka funkcji wygody dostępu do random.org .
BTW-- bym sugerują, że należy dokonać selfanswers CW, jeżeli (1) Państwo umieszczać je niezwłocznie i (2) nie dokonać pytanie CW. W przeciwnym razie wygląda to trochę tak, jakbyś próbował oszukać system rep. YMMV i tak dalej.
dmckee --- kociak byłego moderatora
1
To nie gra w system, tylko rozpoczęcie rzeczy. Nadal może zaakceptować każdą inną odpowiedź.
ars
2
@ars: Może to zaakceptować. Nie będę też próbował zmusić go do korzystania z wiki, jeśli wygra; nie posłuchaj mojej rady. Ale nie opublikuję przygotowanej autoodpowiedzi bez zaznaczenia jej jako wiki, ani nie zagłosuję na taką bez niej. Weź to za to, ile jest warte.
dmckee --- ex-moderator kitten
4
@Dirk: odpowiedź na własne pytanie jest w pełni akceptowalna, nawet zachęcana przez Jeffa i Joela. Nie ma ŻADNEGO wymagania, nawet nieformalnego, aby twoja odpowiedź była CW. Najwyraźniej nie grasz w system. Jeszcze raz zignoruj policję społecznościową wiki.
Julia
8
Muszę się zgodzić, że część stron ma na celu dostarczenie najlepszych odpowiedzi na typowe problemy i ogólne zasoby. Zadanie pytań i udzielenie dobrej odpowiedzi może pomóc wzmocnić temat. Jest to szczególnie przydatne w przypadku nowych / małych tagów, takich jak R.
kpierce8
35
Uważam, że używam with()i within()coraz więcej. Nigdy więcej $zaśmiecania mojego kodu i nie trzeba zaczynać dołączania obiektów do ścieżki wyszukiwania. Mówiąc poważnie, uważam, że with()itp. Sprawiają, że intencja moich skryptów analizy danych jest znacznie jaśniejsza.
> df <- data.frame(A = runif(10), B = rnorm(10))
> A <- 1:10## something else hanging around...
> with(df, A + B) ## I know this will use A in df!
[1] 0.04334784 -0.404446861.993688160.13871605 -1.17734837
[6] 0.424738122.330142261.616907991.419018600.8699079
with()konfiguruje środowisko, w którym jest oceniane wyrażenie R. within()robi to samo, ale umożliwia modyfikację obiektu danych używanego do tworzenia środowiska.
> df <- within(df, C <- rpois(10, lambda = 2))
> head(df)
A B C
10.62635571 -0.5830079120.04810539 -0.4525522130.397069791.5966184340.95802501 -0.8193090250.76772541 -1.9450738260.213350060.21138814
Coś, czego nie zdawałem sobie sprawy, kiedy pierwszy raz użyłem, within()to fakt, że musisz wykonać przypisanie jako część ocenianego wyrażenia i przypisać zwrócony obiekt (jak powyżej), aby uzyskać pożądany efekt.
Odkryłem, że arkusze kalkulacyjne Google to fantastyczny sposób, aby wszyscy współpracownicy znajdowali się na tej samej stronie. Co więcej, Google Forms pozwala na przechwytywanie danych od respondentów i bezproblemowe zapisywanie ich w arkuszu kalkulacyjnym Google. Ponieważ dane zmieniają się często i prawie nigdy nie są ostateczne, lepiej jest, gdy R czyta bezpośrednio arkusz kalkulacyjny Google, niż pobiera pliki csv i odczytuje je.
# Get data from google spreadsheetlibrary(RGoogleDocs)
ps <-readline(prompt="get the password in ")
auth = getGoogleAuth("[email protected]", ps, service="wise")
sheets.con <- getGoogleDocsConnection(auth)
ts2=getWorksheets("Data Collection Repos",sheets.con)
names(ts2)
init.consent <-sheetAsMatrix(ts2$Sheet1,header=TRUE, as.data.frame=TRUE, trim=TRUE)
Nie mogę sobie przypomnieć, które z poniższych poleceń, oprócz jednego lub dwóch, zajmuje kilka sekund.
[Edytuj] Dirk pyta, dlaczego ktoś miałby podawać nieprawidłowe nazwiska? Nie wiem! Ale z pewnością dość często spotykam się z tym problemem w praktyce. Na przykład używając pakietu zmiany kształtu Hadleya:
> library(reshape)
> df$z <- c(1,1,2,2,2)
> recast(df,z~.,id.var="z")
Aggregation requires fun.aggregate: length used as default
z (all)
114226
> recast(df,z~.,id.var="z")$(all)
Error: unexpected '('in"recast(df,z~.,id.var="z")$("
> recast(df,z~.,id.var="z")$`(all)`
Aggregation requires fun.aggregate: length used as default
[1] 46
Moją nową ulubioną rzeczą jest biblioteka foreach. Pozwala na wykonanie wszystkich przyjemnych czynności związanych z zastosowaniem, ale z nieco łatwiejszą składnią:
Najlepsze jest to, że jeśli robisz coś, co faktycznie wymaga znacznej ilości czasu, możesz przełączyć się z %do%do %dopar%(z odpowiednią biblioteką zaplecza), aby natychmiast zrównoleglać, nawet w obrębie klastra. Bardzo zgrabny.
Robię wiele podstawowych operacji na danych, więc oto dwie wbudowane funkcje ( transformacja , podzbiór ) i jedna biblioteka ( sqldf ), których używam codziennie.
stworzyć przykładowe dane sprzedażowe
sales <- expand.grid(country = c('USA', 'UK', 'FR'),
product = c(1, 2, 3))
sales$revenue <- rnorm(dim(sales)[1], mean=100, sd=10)
> sales
country product revenue
1 USA 1108.459652 UK 197.079813 FR 199.662254 USA 2100.347545 UK 287.122626 FR 2112.860847 USA 395.878808 UK 396.435819 FR 394.59259
użyj transform (), aby dodać kolumnę
## transform currency to euros
usd2eur <- 1.434
transform(sales, euro = revenue * usd2eur)
>
country product revenue euro
1 USA 1108.45965155.53112 UK 197.07981139.21253 FR 199.66225142.9157...
użyj sqldf () do wycinania i agregowania za pomocą SQL
Pakiet sqldf zapewnia interfejs SQL dla ramek danych R
## recast the previous subset() expression in SQL
sqldf('SELECT product, revenue FROM sales \
WHERE country = "USA" \
AND product IN (1,2)')
>
product revenue
11108.459722100.3475
Wykonaj agregację lub GROUP BY
sqldf('select country, sum(revenue) revenue \
FROM sales \
GROUP BY country')
>
country revenue
1 FR 307.11572 UK 280.63823 USA 304.6860
Aby uzyskać bardziej wyrafinowaną funkcję zmniejszania map w ramkach danych, sprawdź pakiet plyr . A jeśli znajdziesz się chcąc wyciągnąć włosy, polecam sprawdzanie manipulacji danymi z badań .
Podzbiory „x []” są uśredniane, przy czym każdy podzbiór składa się z tych obserwacji o tych samych poziomach czynników. Użycie: ave (x, ..., FUN = mean)
Jest tu mała pułapka, która cały czas mnie łapała. Jeśli df $ kolumna1 zawiera wartości NA, podzbiór przy użyciu == wyciągnie wszystkie wartości, które są równe x i wszystkie NA. Aby tego uniknąć, użyj „% w%” zamiast „==”.
Matt Parker
Matt, masz absolutną rację i tego nienawidzę, chociaż podoba mi się twoja metoda. Zwykle sprawdzam kolumnę pod kątem NA, a następnie usuwam je za pomocą szybkiej funkcji, którą wykonałem, która pobiera kolumnę ramki danych i zwraca ramkę danych bez wierszy z NA tylko w tej kolumnie.
Dan
Zasadniczo łączę ramkę danych w dół do kolumn, w których muszę mieć wartości, a następnie używam na.omit, aby uzyskać prawidłowe wiersze, a następnie podzbiór oryginalnego zestawu danych tylko z tymi wierszami. Samo użycie na.omit spowodowałoby usunięcie dowolnego wiersza z dowolnym NA, chociaż mogę się mylić.
Dan
16
Czasami potrzebujesz rbindwielu ramek danych. do.call()pozwoli ci to zrobić (ktoś musiał mi to wyjaśnić, gdy bind zadałem to pytanie, ponieważ nie wydaje się to oczywiste zastosowanie).
Dobre połączenie: uważam, że jest to często prostsze niż używanie unsplit.
Richie Cotton
16
W programowaniu R (nie interaktywnych sesji), używam if (bad.condition) stop("message")jest dużo . Każda funkcja zaczyna się od kilku z nich, a kiedy pracuję nad obliczeniami, również je wprowadzam. Chyba przyzwyczaiłem się do używania assert()w C. Korzyści są dwojakie. Po pierwsze, uzyskanie działającego kodu jest dużo szybsze po wprowadzeniu tych sprawdzeń. Po drugie, i prawdopodobnie ważniejsze, o wiele łatwiej jest pracować z istniejącym kodem, gdy widzisz te kontrole na każdym ekranie w swoim edytorze. Nie będziesz musiał się zastanawiać x>0, czy zaufać komentarzowi stwierdzającemu, że jest ... będziesz wiedział , na pierwszy rzut oka, że tak jest.
Niezły nawyk, a R oferuje jeszcze inny sposób: stopfifnot(!bad.condition)który jest bardziej zwięzły.
Dirk Eddelbuettel
13
traceback()Funkcja jest koniecznością kiedy masz gdzieś błąd i nie rozumiem go łatwo. Wyświetli ślad stosu, co jest bardzo pomocne, ponieważ R domyślnie nie jest zbyt rozwlekły.
Wtedy ustawienie options(error=recover)pozwoli Ci „wejść” do funkcji podnoszącej błąd i spróbować zrozumieć, co się dokładnie dzieje, tak jakbyś miał nad nią pełną kontrolę i mógł browser()w niej umieścić .
Te trzy funkcje mogą naprawdę pomóc w debugowaniu kodu.
options(error=recover)to moja ulubiona metoda debugowania.
Joshua Ulrich
12
Jestem naprawdę zaskoczony, że nikt nie opublikował na temat aplikacji, tapply, lapply i sapply. Ogólna zasada, której używam podczas robienia rzeczy w R, jest taka, że jeśli mam pętlę for, która przetwarza dane lub przeprowadza symulacje, próbuję ją rozłożyć na czynniki i zastąpić *. Niektórzy ludzie unikają funkcji * Apply, ponieważ uważają, że można przekazywać tylko funkcje pojedynczego parametru. Nic nie może być dalsze od prawdy! Podobnie jak w przypadku przekazywania funkcji z parametrami jako obiektów pierwszej klasy w JavaScript, robisz to w języku R z funkcjami anonimowymi. Na przykład:
> sapply(rnorm(100, 0, 1), round)
[1] 11011 -1 -2022 -2 -101 -101 -10 -100000
[26] 20 -1 -2001 -1151 -1011120 -11 -110 -11
[51] 211 -2 -10 -12 -11 -11 -10 -1 -2110 -1 -11120
[76] 000 -2 -111 -21 -1111000 -1 -30 -100011
> sapply(rnorm(100, 0, 1), round(x, 2)) # How can we pass a parameter?
Error in match.fun(FUN) : object 'x' not found
# Wrap your function call in an anonymous function to use parameters
> sapply(rnorm(100, 0, 1), function(x) {round(x, 2)})
[1] -0.05 -1.74 -0.09 -1.230.69 -1.430.760.550.96 -0.47 -0.81 -0.47
[13] 0.270.320.47 -1.28 -1.44 -1.930.51 -0.82 -0.06 -1.411.23 -0.26
[25] 0.22 -0.04 -2.170.60 -0.10 -0.920.132.621.03 -1.33 -1.73 -0.08
[37] 0.45 -0.930.400.051.09 -1.23 -0.350.620.01 -1.081.70 -1.27
[49] 0.550.60 -1.461.08 -1.88 -0.150.210.060.53 -1.16 -2.13 -0.03
[61] 0.33 -1.070.980.62 -0.01 -0.53 -1.17 -0.28 -0.950.71 -0.58 -0.03
[73] -1.47 -0.75 -0.540.42 -1.630.05 -1.900.40 -0.010.14 -1.581.37
[85] -1.00 -0.901.69 -0.11 -2.19 -0.741.34 -0.75 -0.51 -0.99 -0.36 -1.63
[97] -0.980.611.010.55# Note that anonymous functions aren't being called, but being passed.
> function() {print('hello #rstats')}()
function() {print('hello #rstats')}()
> a = function() {print('hello #rstats')}
> a
function() {print('hello #rstats')}
> a()
[1] "hello #rstats"
(Dla tych, którzy śledzą #rstats, również to tam opublikowałem).
Pamiętaj, użyj aplikacji Apply, Sapply, Lapply, Tapply i do. Call! Skorzystaj z wektoryzacji R. Nigdy nie powinieneś podchodzić do zestawu kodu R i zobaczyć:
N = 10000
l = numeric()
for (i in seq(1:N)) {
sim <- rnorm(1, 0, 1)
l <- rbind(l, sim)
}
Nie tylko nie jest to wektoryzowane, ale struktura tablicy w R nie jest powiększana tak, jak w Pythonie (podwajanie rozmiaru, gdy skończy się miejsce, IIRC). Więc każdy krok rbind musi najpierw urosnąć na tyle, aby zaakceptować wyniki rbind (), a następnie skopiować całą zawartość poprzedniego l. Dla zabawy wypróbuj powyższe w R. Zwróć uwagę, jak długo to trwa (nie potrzebujesz nawet Rprof ani żadnej funkcji czasowej). Więc spróbuj
N=10000
l <- rnorm(N, 0, 1)
Poniższe są również lepsze niż pierwsza wersja:
N = 10000
l = numeric(N)
for (i in seq(1:N)) {
sim <- rnorm(1, 0, 1)
l[i] <- sim
}
zastosować, sapply, lapply i tapply są przydatne. Jeśli chcesz przekazać parametry do nazwanej funkcji, takiej jak round, możesz po prostu przekazać ją razem z Apply zamiast pisać funkcję anonimową. Spróbuj „sapply (rnorm (10, 0, 1), round, digits = 2)”, co daje wynik „[1] -0,29 0,29 1,31 -0,06 -1,90 -0,84 0,21 0,02 0,23 -1,10”.
Daniel
11
Za radą Dirka zamieszczam pojedyncze przykłady. Mam nadzieję, że nie są zbyt „urocze” [sprytne, ale mnie to nie obchodzi] ani trywialne dla tej publiczności.
Modele liniowe są chlebem powszednim R. Gdy liczba zmiennych niezależnych jest wysoka, można wybrać dwie możliwości. Pierwszym jest użycie lm.fit (), które otrzymuje macierz projektową x i odpowiedź y jako argumenty, podobnie jak w Matlabie. Wadą tego podejścia jest to, że zwracaną wartością jest lista obiektów (dopasowanych współczynników, reszt itp.), A nie obiekt klasy „lm”, który można ładnie podsumować, wykorzystać do predykcji, selekcji krokowej itp. podejście polega na stworzeniu formuły:
> A
X1 X2 X3 X4 y
10.968523630.338271070.2613322570.628170211.642532620.080127550.691598280.0879941580.937804810.980130430.101675450.381193040.8652098320.165016620.483087340.066994580.417564150.2580716160.340277750.7508766...
> (f=paste("y ~",paste(names(A)[1:4],collapse=" + ")))
[1] "y ~ X1 + X2 + X3 + X4"
> lm(formula(f),data=A)
Call:
lm(formula = formula(f), data = A)
Coefficients:
(Intercept) X1 X2 X3 X4
0.782360.95406 -0.06738 -0.43686 -0.06644
Co powiesz na to, że wybierzesz jeden na post i zilustrujesz przykładem? Możemy wtedy działać przez wiele dni i publikować nowe przykłady z nowymi poleceniami ... [BTW: Jak pamiętam, potrzebujesz as.formula (wklej (...)) do użycia formuły. ]
Dirk Eddelbuettel,
Nie musisz jawnie tworzyć formuły, aby pokryć wszystkie kolumny, ponieważ obejmuje to format „y ~. - 1”. „.” oznacza „wszystkie kolumny z wyjątkiem zmiennej zależnej, a„ - 1 ”wyklucza stałą, jak w przykładzie.
Dirk Eddelbuettel
To prawda w tym konkretnym przykładzie, ale dla X z ncols >> nrows, często usuwam niektóre zmienne niezależne, szczególnie w końcowych etapach analizy. W takim przypadku tworzenie formuły na podstawie nazw ramek danych jest nadal przydatne.
gappy
10
Możesz przypisać wartość zwracaną z bloku if-else.
Zamiast np
condition <- runif(1) > 0.5if(condition) x <- 1else x <- 2
Możesz również zrobić to tak, jak x <- ifelse (condition, 1, 2), w którym to przypadku każdy komponent jest wektoryzowany.
Shane
Shane, mógłbyś, ale chyba że naprawdę głęboko zastanawiasz się, co robi ifelse (), prawdopodobnie nie powinieneś! Łatwo jest źle zrozumieć ...
Harlan
Co w tym magicznego? Tak właśnie if-then-elsedziałają wyrażenia w każdym języku funkcjonalnym (nie mylić ze if-then-elsestwierdzeniami ). Bardzo podobny do trójskładnikowego ?:operatora języków podobnych do C.
Frank
10
Jako totalny noob dla R i nowicjusz w statystykach, uwielbiam unclass()
drukować wszystkie elementy ramki danych jako zwykłą listę.
Jest to bardzo przydatne, gdy spojrzysz na pełny zestaw danych za jednym razem, aby szybko przyjrzeć się potencjalnym problemom.
CrossTable()z gmodelspakietu zapewnia łatwy dostęp do tabel przestawnych typu SAS i SPSS, wraz ze zwykłymi testami (Chisq, McNemar itp.). Zasadniczo ma xtabs()fantazyjną wydajność i kilka dodatkowych testów - ale ułatwia dzielenie się wynikami z poganami.
Ładny!! Używam dość często modeli gmodels, ale przegapiłem ten
Abhijit
Dobra odpowiedź, wszystko, co może powstrzymać mnie od nadmiernego objaśniania tabel z poganami, to dobre wykorzystanie czasu.
Stedy
7
Ostatecznie system(). Możliwość dostępu do wszystkich narzędzi unixowych (przynajmniej pod Linuksem / MacOSX) z wnętrza środowiska R szybko stała się nieoceniona w moim codziennym przepływie pracy.
To wiąże się z moim wcześniejszym komentarzem na temat połączeń: możesz również użyć pipe () do przekazywania danych z lub do poleceń systemu Unix. Zobacz help(connections)szczegóły i przykłady.
Dirk Eddelbuettel
6
Oto irytujące obejście polegające na zamianie współczynnika na liczbowy. (Podobnie jak w przypadku innych typów danych)
Może miałeś na myśli wektor „w postać”. W takim przypadku „as.character (old.var)” jest prostsze.
Dirk Eddelbuettel
1
Zawsze uważałem, że ta rada (którą można czytać na współczynniku) była błędna. Musisz być pewien, że old.var jest czynnikiem, a to będzie się różnić w zależności od opcji ustawionych dla sesji R. Używanie as.numeric (as.character (old.var)) jest zarówno bezpieczniejsze, jak i czystsze.
Eduardo Leoni
Naprawdę nie warto negatywnie oceniać, ale nieważne. To działa dla mnie.
Ryan R. Rosario
Ryan - Czy mógłbyś naprawić swój kod? Jeśli stary.var <- współczynnik (1: 2); Twój kod da [1] "1" "2" (nie numeryczne). Być może miałeś na myśli as.numeric (poziomy (stary.var) [stary.var])?
Eduardo Leoni
3
Lub trochę wydajniej:as.numeric(levels(old.var))[old.var]
hadley,
6
Chociaż to pytanie pojawia się od jakiegoś czasu, niedawno odkryłem na blogu SAS i R świetną sztuczkę dotyczącą używania polecenia cut. Polecenie służy do dzielenia danych na kategorie i użyję zbioru danych tęczówki jako przykładu i podzielę go na 10 kategorii:
Kolejna sztuczka. Niektóre pakiety, jak glmnet, tylko przyjąć jako wejścia macierz projektowania i zmienną odpowiedzi. Jeśli ktoś chce dopasować model do wszystkich interakcji między cechami, nie może użyć formuły „y ~. ^ 2”. Używanie expand.grid()pozwala nam skorzystać z potężnego indeksowania tablic i operacji na wektorach R.
Jeśli funkcja modelująca nie akceptuje formuły (co jest bardzo rzadkie!), Czy nie byłoby lepiej skonstruować macierz projektu za pomocą model.matrix?
Hadley
Niezłe. Nie wiedziałem o istnieniu tej funkcji. Powyższa funkcja jest równoważna model.matrix (~. ^ 2-1, X) Ale jeśli chodzi o przekazywanie macierzy, poza glmnet, często przekazuję wskaźniki tablic do niestandardowych funkcji C. Rzeczywiście, nie wiedziałbym, jak przekazać formułę do funkcji. Czy masz przykład zabawki?
gappy
5
Jedną z moich ulubionych, jeśli nie nieco niekonwencjonalnych sztuczek, jest użycie eval()i parse(). Ten przykład może być ilustracją tego, jak może to być pomocne
Tego typu sytuacje zdarzają się częściej niż nie, a wykorzystanie eval()i parse()może pomóc w rozwiązaniu tego problemu. Oczywiście cieszę się z wszelkich opinii na temat alternatywnych sposobów kodowania tego.
Można to również zrobić za pomocą nazwanych elementów wektorowych.
Dirk Eddelbuettel
3
biblioteka (fortunes); fortune (106) Jeśli odpowiedź brzmi parse (), zwykle należy ponownie przemyśleć pytanie. - Thomas Lumley R-help (luty 2005)
Eduardo Leoni
Oto przykład, w którym eval () i parse () mogą być przydatne. Obejmuje to pakiet Bioconductor, np. Hgu133a.db i gdzie próbujesz uzyskać różne informacje o identyfikatorze sondy. Na przykład: parametr biblioteki (hgu133a.db) <- 'SYMBOL' mget ('202431_s_at', env = eval (parse (text = paste ('hgu133a', parameter, sep = '')))) parametr <- 'ENTREZID 'mget (' 202431_s_at ', env = eval (parse (text = paste (' hgu133a ', parameter, sep =' '))))
andrewj
Jak mówi Dirk, lepiej jest to zrobić z nazwanymi elementami wektorowymi lub `get (paste (state, parameter, sep = '.'))`
hadley
@Hadley, nie wiedziałem, że możesz użyć get () w ten sposób. Dzięki.
andrewj
5
set.seed() ustawia stan generatora liczb losowych.
for (f in files) {if (! (f == 'mysource.r')) {print (paste ('Sourcing', f)) source (paste (d, f, sep = ''))}}
Używam powyższego kodu do pozyskiwania wszystkich plików w katalogu podczas uruchamiania z różnymi programami narzędziowymi, których używam podczas mojej sesji interaktywnej z R. Jestem pewien, że są lepsze sposoby, ale uważam, że jest to przydatne w mojej pracy. Linia, która to robi, jest następująca.
Dzięki. Patrzyłem na wątek lub dwa na roxygen i wydaje mi się, że prawdopodobnie jestem na poziomie, na którym powinienem spróbować napisać prosty pakiet do samodzielnego użytku.
mcheema
3
Wykonywanie operacji na wielu zmiennych w ramce danych. To zostało skradzione z subset.data.frame.
get.vars<-function(vars,data){
nl <- as.list(1L:ncol(data))
names(nl) <- names(data)
vars <- eval(substitute(vars), nl, parent.frame())
data[,vars]
#do stuff here
}
get.vars(c(cyl:hwy,class),mpg)
Na początku wydaje się to fajne, ale tego rodzaju kod na dłuższą metę nie sprawi ci końca. Zawsze lepiej jest mówić wprost.
Hadley
bum, ostatnio dość często używam tej sztuczki. Czy mógłbyś bardziej szczegółowo opisać jego nieograniczone problemy?
Ian Fellows
Może hadley sugeruje użycie zamiast tego pakietu plyr?
Christopher DuBois
3
Nie, to nie jest zawoalowana sugestia, aby zamiast tego użyć Plyr. Zasadniczy problem z twoim kodem polega na tym, że jest on semantycznie leniwy - zamiast zmuszać użytkownika do jawnego przeliterowania tego, czego chce, robisz trochę "magii", aby odgadnąć. Problem polega na tym, że bardzo utrudnia to programowanie funkcji - tj. Trudno jest napisać funkcję, która wywołuje get.varsbez przeskakiwania przez całą masę kółek.
Hadley
3
Opublikowałem to już raz, ale używam go tak często, że pomyślałem, że opublikuję go ponownie. To tylko niewielka funkcja zwracająca nazwy i numery pozycji ramki data.frame. Nie jest to nic specjalnego, ale prawie nigdy nie przechodzę przez sesję bez wielokrotnego korzystania z niej.
##creates an object from a data.frame listing the column names and location
Odpowiedzi:
str()
informuje o strukturze dowolnego obiektu.źródło
dir()
- ma więcej sensu.str
jest też skrótemstring
.class()
? Wydaje się, że ujawnia podobny rodzaj informacji. Dlaczego istnieją dwa takie podobne polecenia?class()
to tylko niewielka część informacji, którestr()
wyświetlaBardzo przydatną funkcją, której często używam, jest dput (), która pozwala na zrzucenie obiektu w postaci kodu R.
# Use the iris data set R> data(iris) # dput of a numeric vector R> dput(iris$Petal.Length) c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1, 1.7, 1.9, 1.6, 1.6, 1.5, 1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5, 4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7, 3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3, 4.4, 4.8, 5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4, 4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3, 3, 4.1, 6, 5.1, 5.9, 5.6, 5.8, 6.6, 4.5, 6.3, 5.8, 6.1, 5.1, 5.3, 5.5, 5, 5.1, 5.3, 5.5, 6.7, 6.9, 5, 5.7, 4.9, 6.7, 4.9, 5.7, 6, 4.8, 4.9, 5.6, 5.8, 6.1, 6.4, 5.6, 5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1, 5.9, 5.7, 5.2, 5, 5.2, 5.4, 5.1) # dput of a factor levels R> dput(levels(iris$Species)) c("setosa", "versicolor", "virginica")
Bardzo przydatne może być publikowanie łatwo odtwarzalnych fragmentów danych, gdy prosisz o pomoc lub edytujesz lub zmieniasz kolejność poziomów współczynnika.
źródło
head () i tail (), aby uzyskać pierwszą i ostatnią część ramki danych, wektora, macierzy, funkcji itp. Szczególnie w przypadku dużych ramek danych jest to szybki sposób sprawdzenia, czy został załadowany prawidłowo.
źródło
Jedna fajna funkcja: odczyt danych wykorzystuje połączenia, które mogą być plikami lokalnymi, plikami zdalnymi dostępnymi przez http, potokami z innych programów lub więcej.
Jako prosty przykład rozważmy ten dostęp dla N = 10 losowych liczb całkowitych od min = 100 do max = 200 z random.org (który dostarcza prawdziwe liczby losowe oparte na szumie atmosferycznym, a nie na generatorze liczb pseudolosowych):
R> site <- "http://random.org/integers/" # base URL R> query <- "num=10&min=100&max=200&col=2&base=10&format=plain&rnd=new" R> txt <- paste(site, query, sep="?") # concat url and query string R> nums <- read.table(file=txt) # and read the data R> nums # and show it V1 V2 1 165 143 2 107 118 3 103 132 4 191 100 5 138 185 R>
Tak na marginesie, losowo pakiet zawiera kilka funkcji wygody dostępu do random.org .
źródło
Uważam, że używam
with()
iwithin()
coraz więcej. Nigdy więcej$
zaśmiecania mojego kodu i nie trzeba zaczynać dołączania obiektów do ścieżki wyszukiwania. Mówiąc poważnie, uważam, żewith()
itp. Sprawiają, że intencja moich skryptów analizy danych jest znacznie jaśniejsza.> df <- data.frame(A = runif(10), B = rnorm(10)) > A <- 1:10 ## something else hanging around... > with(df, A + B) ## I know this will use A in df! [1] 0.04334784 -0.40444686 1.99368816 0.13871605 -1.17734837 [6] 0.42473812 2.33014226 1.61690799 1.41901860 0.8699079
with()
konfiguruje środowisko, w którym jest oceniane wyrażenie R.within()
robi to samo, ale umożliwia modyfikację obiektu danych używanego do tworzenia środowiska.> df <- within(df, C <- rpois(10, lambda = 2)) > head(df) A B C 1 0.62635571 -0.5830079 1 2 0.04810539 -0.4525522 1 3 0.39706979 1.5966184 3 4 0.95802501 -0.8193090 2 5 0.76772541 -1.9450738 2 6 0.21335006 0.2113881 4
Coś, czego nie zdawałem sobie sprawy, kiedy pierwszy raz użyłem,
within()
to fakt, że musisz wykonać przypisanie jako część ocenianego wyrażenia i przypisać zwrócony obiekt (jak powyżej), aby uzyskać pożądany efekt.źródło
Sztuczka wprowadzania danych = pakiet RGoogleDocs
http://www.omegahat.org/RGoogleDocs/
Odkryłem, że arkusze kalkulacyjne Google to fantastyczny sposób, aby wszyscy współpracownicy znajdowali się na tej samej stronie. Co więcej, Google Forms pozwala na przechwytywanie danych od respondentów i bezproblemowe zapisywanie ich w arkuszu kalkulacyjnym Google. Ponieważ dane zmieniają się często i prawie nigdy nie są ostateczne, lepiej jest, gdy R czyta bezpośrednio arkusz kalkulacyjny Google, niż pobiera pliki csv i odczytuje je.
# Get data from google spreadsheet library(RGoogleDocs) ps <-readline(prompt="get the password in ") auth = getGoogleAuth("[email protected]", ps, service="wise") sheets.con <- getGoogleDocsConnection(auth) ts2=getWorksheets("Data Collection Repos",sheets.con) names(ts2) init.consent <-sheetAsMatrix(ts2$Sheet1,header=TRUE, as.data.frame=TRUE, trim=TRUE)
Nie mogę sobie przypomnieć, które z poniższych poleceń, oprócz jednego lub dwóch, zajmuje kilka sekund.
getGoogleAuth
getGoogleDocsConnection
getWorksheets
źródło
Użyj odwrotnych znaków, aby odwołać się do niestandardowych nazw.
> df <- data.frame(x=rnorm(5),y=runif(5)) > names(df) <- 1:2 > df 1 2 1 -1.2035003 0.6989573 2 -1.2146266 0.8272276 3 0.3563335 0.0947696 4 -0.4372646 0.9765767 5 -0.9952423 0.6477714 > df$1 Error: unexpected numeric constant in "df$1" > df$`1` [1] -1.2035003 -1.2146266 0.3563335 -0.4372646 -0.9952423
W tym przypadku działałoby również df [, "1"]. Ale kleszcze działają w formułach!
> lm(`2`~`1`,data=df) Call: lm(formula = `2` ~ `1`, data = df) Coefficients: (Intercept) `1` 0.4087 -0.3440
[Edytuj] Dirk pyta, dlaczego ktoś miałby podawać nieprawidłowe nazwiska? Nie wiem! Ale z pewnością dość często spotykam się z tym problemem w praktyce. Na przykład używając pakietu zmiany kształtu Hadleya:
> library(reshape) > df$z <- c(1,1,2,2,2) > recast(df,z~.,id.var="z") Aggregation requires fun.aggregate: length used as default z (all) 1 1 4 2 2 6 > recast(df,z~.,id.var="z")$(all) Error: unexpected '(' in "recast(df,z~.,id.var="z")$(" > recast(df,z~.,id.var="z")$`(all)` Aggregation requires fun.aggregate: length used as default [1] 4 6
źródło
read.table
gdycheck.names
jest fałszywe - tj. Gdy chcesz pracować z oryginalnymi nazwami kolumn.Nie wiem, jak dobrze to jest / nie jest znane, ale zdecydowanie skorzystałem z możliwości przekazywania przez referencje środowisk.
zz <- new.env() zz$foo <- c(1,2,3,4,5) changer <- function(blah) { blah$foo <- 5 } changer(zz) zz$foo
W tym przykładzie nie ma sensu, dlaczego miałoby to być przydatne, ale jeśli mijasz wokół dużych obiektów, może to pomóc.
źródło
Moją nową ulubioną rzeczą jest biblioteka foreach. Pozwala na wykonanie wszystkich przyjemnych czynności związanych z zastosowaniem, ale z nieco łatwiejszą składnią:
list_powers <- foreach(i = 1:100) %do% { lp <- x[i]^i return (lp) }
Najlepsze jest to, że jeśli robisz coś, co faktycznie wymaga znacznej ilości czasu, możesz przełączyć się z
%do%
do%dopar%
(z odpowiednią biblioteką zaplecza), aby natychmiast zrównoleglać, nawet w obrębie klastra. Bardzo zgrabny.źródło
Robię wiele podstawowych operacji na danych, więc oto dwie wbudowane funkcje ( transformacja , podzbiór ) i jedna biblioteka ( sqldf ), których używam codziennie.
stworzyć przykładowe dane sprzedażowe
sales <- expand.grid(country = c('USA', 'UK', 'FR'), product = c(1, 2, 3)) sales$revenue <- rnorm(dim(sales)[1], mean=100, sd=10) > sales country product revenue 1 USA 1 108.45965 2 UK 1 97.07981 3 FR 1 99.66225 4 USA 2 100.34754 5 UK 2 87.12262 6 FR 2 112.86084 7 USA 3 95.87880 8 UK 3 96.43581 9 FR 3 94.59259
użyj transform (), aby dodać kolumnę
## transform currency to euros usd2eur <- 1.434 transform(sales, euro = revenue * usd2eur) > country product revenue euro 1 USA 1 108.45965 155.5311 2 UK 1 97.07981 139.2125 3 FR 1 99.66225 142.9157 ...
użyj subset (), aby wyciąć dane
subset(sales, country == 'USA' & product %in% c(1, 2), select = c('product', 'revenue')) > product revenue 1 1 108.4597 4 2 100.3475
użyj sqldf () do wycinania i agregowania za pomocą SQL
Pakiet sqldf zapewnia interfejs SQL dla ramek danych R
## recast the previous subset() expression in SQL sqldf('SELECT product, revenue FROM sales \ WHERE country = "USA" \ AND product IN (1,2)') > product revenue 1 1 108.4597 2 2 100.3475
Wykonaj agregację lub GROUP BY
sqldf('select country, sum(revenue) revenue \ FROM sales \ GROUP BY country') > country revenue 1 FR 307.1157 2 UK 280.6382 3 USA 304.6860
Aby uzyskać bardziej wyrafinowaną funkcję zmniejszania map w ramkach danych, sprawdź pakiet plyr . A jeśli znajdziesz się chcąc wyciągnąć włosy, polecam sprawdzanie manipulacji danymi z badań .
źródło
Podzbiory „x []” są uśredniane, przy czym każdy podzbiór składa się z tych obserwacji o tych samych poziomach czynników. Użycie: ave (x, ..., FUN = mean)
Używam go cały czas. (np. w tej odpowiedzi tutaj w so )
źródło
Sposób na przyspieszenie kodu i wyeliminowanie pętli.
zamiast pętli for, które przechodzą przez ramkę danych w poszukiwaniu wartości. po prostu weź podzbiór df z tymi wartościami, znacznie szybciej.
więc zamiast:
for(i in 1:nrow(df)){ if (df$column[i] == x) { df$column2[i] <- y or any other similiar code } }
zrób coś takiego:
ta podstawowa koncepcja ma zastosowanie niezwykle często i jest świetnym sposobem na pozbycie się pętli for
źródło
Czasami potrzebujesz
rbind
wielu ramek danych.do.call()
pozwoli ci to zrobić (ktoś musiał mi to wyjaśnić, gdy bind zadałem to pytanie, ponieważ nie wydaje się to oczywiste zastosowanie).foo <- list() foo[[1]] <- data.frame(a=1:5, b=11:15) foo[[2]] <- data.frame(a=101:105, b=111:115) foo[[3]] <- data.frame(a=200:210, b=300:310) do.call(rbind, foo)
źródło
unsplit
.W programowaniu R (nie interaktywnych sesji), używam
if (bad.condition) stop("message")
jest dużo . Każda funkcja zaczyna się od kilku z nich, a kiedy pracuję nad obliczeniami, również je wprowadzam. Chyba przyzwyczaiłem się do używaniaassert()
w C. Korzyści są dwojakie. Po pierwsze, uzyskanie działającego kodu jest dużo szybsze po wprowadzeniu tych sprawdzeń. Po drugie, i prawdopodobnie ważniejsze, o wiele łatwiej jest pracować z istniejącym kodem, gdy widzisz te kontrole na każdym ekranie w swoim edytorze. Nie będziesz musiał się zastanawiaćx>0
, czy zaufać komentarzowi stwierdzającemu, że jest ... będziesz wiedział , na pierwszy rzut oka, że tak jest.PS. mój pierwszy post tutaj. Bądź delikatny!
źródło
stopfifnot(!bad.condition)
który jest bardziej zwięzły.traceback()
Funkcja jest koniecznością kiedy masz gdzieś błąd i nie rozumiem go łatwo. Wyświetli ślad stosu, co jest bardzo pomocne, ponieważ R domyślnie nie jest zbyt rozwlekły.Wtedy ustawienie
options(error=recover)
pozwoli Ci „wejść” do funkcji podnoszącej błąd i spróbować zrozumieć, co się dokładnie dzieje, tak jakbyś miał nad nią pełną kontrolę i mógłbrowser()
w niej umieścić .Te trzy funkcje mogą naprawdę pomóc w debugowaniu kodu.
źródło
options(error=recover)
to moja ulubiona metoda debugowania.Jestem naprawdę zaskoczony, że nikt nie opublikował na temat aplikacji, tapply, lapply i sapply. Ogólna zasada, której używam podczas robienia rzeczy w R, jest taka, że jeśli mam pętlę for, która przetwarza dane lub przeprowadza symulacje, próbuję ją rozłożyć na czynniki i zastąpić *. Niektórzy ludzie unikają funkcji * Apply, ponieważ uważają, że można przekazywać tylko funkcje pojedynczego parametru. Nic nie może być dalsze od prawdy! Podobnie jak w przypadku przekazywania funkcji z parametrami jako obiektów pierwszej klasy w JavaScript, robisz to w języku R z funkcjami anonimowymi. Na przykład:
> sapply(rnorm(100, 0, 1), round) [1] 1 1 0 1 1 -1 -2 0 2 2 -2 -1 0 1 -1 0 1 -1 0 -1 0 0 0 0 0 [26] 2 0 -1 -2 0 0 1 -1 1 5 1 -1 0 1 1 1 2 0 -1 1 -1 1 0 -1 1 [51] 2 1 1 -2 -1 0 -1 2 -1 1 -1 1 -1 0 -1 -2 1 1 0 -1 -1 1 1 2 0 [76] 0 0 0 -2 -1 1 1 -2 1 -1 1 1 1 0 0 0 -1 -3 0 -1 0 0 0 1 1 > sapply(rnorm(100, 0, 1), round(x, 2)) # How can we pass a parameter? Error in match.fun(FUN) : object 'x' not found # Wrap your function call in an anonymous function to use parameters > sapply(rnorm(100, 0, 1), function(x) {round(x, 2)}) [1] -0.05 -1.74 -0.09 -1.23 0.69 -1.43 0.76 0.55 0.96 -0.47 -0.81 -0.47 [13] 0.27 0.32 0.47 -1.28 -1.44 -1.93 0.51 -0.82 -0.06 -1.41 1.23 -0.26 [25] 0.22 -0.04 -2.17 0.60 -0.10 -0.92 0.13 2.62 1.03 -1.33 -1.73 -0.08 [37] 0.45 -0.93 0.40 0.05 1.09 -1.23 -0.35 0.62 0.01 -1.08 1.70 -1.27 [49] 0.55 0.60 -1.46 1.08 -1.88 -0.15 0.21 0.06 0.53 -1.16 -2.13 -0.03 [61] 0.33 -1.07 0.98 0.62 -0.01 -0.53 -1.17 -0.28 -0.95 0.71 -0.58 -0.03 [73] -1.47 -0.75 -0.54 0.42 -1.63 0.05 -1.90 0.40 -0.01 0.14 -1.58 1.37 [85] -1.00 -0.90 1.69 -0.11 -2.19 -0.74 1.34 -0.75 -0.51 -0.99 -0.36 -1.63 [97] -0.98 0.61 1.01 0.55 # Note that anonymous functions aren't being called, but being passed. > function() {print('hello #rstats')}() function() {print('hello #rstats')}() > a = function() {print('hello #rstats')} > a function() {print('hello #rstats')} > a() [1] "hello #rstats"
(Dla tych, którzy śledzą #rstats, również to tam opublikowałem).
Pamiętaj, użyj aplikacji Apply, Sapply, Lapply, Tapply i do. Call! Skorzystaj z wektoryzacji R. Nigdy nie powinieneś podchodzić do zestawu kodu R i zobaczyć:
N = 10000 l = numeric() for (i in seq(1:N)) { sim <- rnorm(1, 0, 1) l <- rbind(l, sim) }
Nie tylko nie jest to wektoryzowane, ale struktura tablicy w R nie jest powiększana tak, jak w Pythonie (podwajanie rozmiaru, gdy skończy się miejsce, IIRC). Więc każdy krok rbind musi najpierw urosnąć na tyle, aby zaakceptować wyniki rbind (), a następnie skopiować całą zawartość poprzedniego l. Dla zabawy wypróbuj powyższe w R. Zwróć uwagę, jak długo to trwa (nie potrzebujesz nawet Rprof ani żadnej funkcji czasowej). Więc spróbuj
N=10000 l <- rnorm(N, 0, 1)
Poniższe są również lepsze niż pierwsza wersja:
N = 10000 l = numeric(N) for (i in seq(1:N)) { sim <- rnorm(1, 0, 1) l[i] <- sim }
źródło
Za radą Dirka zamieszczam pojedyncze przykłady. Mam nadzieję, że nie są zbyt „urocze” [sprytne, ale mnie to nie obchodzi] ani trywialne dla tej publiczności.
Modele liniowe są chlebem powszednim R. Gdy liczba zmiennych niezależnych jest wysoka, można wybrać dwie możliwości. Pierwszym jest użycie lm.fit (), które otrzymuje macierz projektową x i odpowiedź y jako argumenty, podobnie jak w Matlabie. Wadą tego podejścia jest to, że zwracaną wartością jest lista obiektów (dopasowanych współczynników, reszt itp.), A nie obiekt klasy „lm”, który można ładnie podsumować, wykorzystać do predykcji, selekcji krokowej itp. podejście polega na stworzeniu formuły:
> A X1 X2 X3 X4 y 1 0.96852363 0.33827107 0.261332257 0.62817021 1.6425326 2 0.08012755 0.69159828 0.087994158 0.93780481 0.9801304 3 0.10167545 0.38119304 0.865209832 0.16501662 0.4830873 4 0.06699458 0.41756415 0.258071616 0.34027775 0.7508766 ... > (f=paste("y ~",paste(names(A)[1:4],collapse=" + "))) [1] "y ~ X1 + X2 + X3 + X4" > lm(formula(f),data=A) Call: lm(formula = formula(f), data = A) Coefficients: (Intercept) X1 X2 X3 X4 0.78236 0.95406 -0.06738 -0.43686 -0.06644
źródło
Możesz przypisać wartość zwracaną z bloku if-else.
Zamiast np
condition <- runif(1) > 0.5 if(condition) x <- 1 else x <- 2
możesz to zrobić
x <- if(condition) 1 else 2
Dokładnie jak to działa, to głęboka magia.
źródło
if-then-else
działają wyrażenia w każdym języku funkcjonalnym (nie mylić zeif-then-else
stwierdzeniami ). Bardzo podobny do trójskładnikowego?:
operatora języków podobnych do C.Jako totalny noob dla R i nowicjusz w statystykach, uwielbiam
unclass()
drukować wszystkie elementy ramki danych jako zwykłą listę.Jest to bardzo przydatne, gdy spojrzysz na pełny zestaw danych za jednym razem, aby szybko przyjrzeć się potencjalnym problemom.
źródło
CrossTable()
zgmodels
pakietu zapewnia łatwy dostęp do tabel przestawnych typu SAS i SPSS, wraz ze zwykłymi testami (Chisq, McNemar itp.). Zasadniczo maxtabs()
fantazyjną wydajność i kilka dodatkowych testów - ale ułatwia dzielenie się wynikami z poganami.źródło
Ostatecznie
system()
. Możliwość dostępu do wszystkich narzędzi unixowych (przynajmniej pod Linuksem / MacOSX) z wnętrza środowiska R szybko stała się nieoceniona w moim codziennym przepływie pracy.źródło
help(connections)
szczegóły i przykłady.Oto irytujące obejście polegające na zamianie współczynnika na liczbowy. (Podobnie jak w przypadku innych typów danych)
źródło
as.numeric(levels(old.var))[old.var]
Chociaż to pytanie pojawia się od jakiegoś czasu, niedawno odkryłem na blogu SAS i R świetną sztuczkę dotyczącą używania polecenia
cut
. Polecenie służy do dzielenia danych na kategorie i użyję zbioru danych tęczówki jako przykładu i podzielę go na 10 kategorii:> irisSL <- iris$Sepal.Length > str(irisSL) num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ... > cut(irisSL, 10) [1] (5.02,5.38] (4.66,5.02] (4.66,5.02] (4.3,4.66] (4.66,5.02] (5.38,5.74] (4.3,4.66] (4.66,5.02] (4.3,4.66] (4.66,5.02] [11] (5.38,5.74] (4.66,5.02] (4.66,5.02] (4.3,4.66] (5.74,6.1] (5.38,5.74] (5.38,5.74] (5.02,5.38] (5.38,5.74] (5.02,5.38] [21] (5.38,5.74] (5.02,5.38] (4.3,4.66] (5.02,5.38] (4.66,5.02] (4.66,5.02] (4.66,5.02] (5.02,5.38] (5.02,5.38] (4.66,5.02] [31] (4.66,5.02] (5.38,5.74] (5.02,5.38] (5.38,5.74] (4.66,5.02] (4.66,5.02] (5.38,5.74] (4.66,5.02] (4.3,4.66] (5.02,5.38] [41] (4.66,5.02] (4.3,4.66] (4.3,4.66] (4.66,5.02] (5.02,5.38] (4.66,5.02] (5.02,5.38] (4.3,4.66] (5.02,5.38] (4.66,5.02] [51] (6.82,7.18] (6.1,6.46] (6.82,7.18] (5.38,5.74] (6.46,6.82] (5.38,5.74] (6.1,6.46] (4.66,5.02] (6.46,6.82] (5.02,5.38] [61] (4.66,5.02] (5.74,6.1] (5.74,6.1] (5.74,6.1] (5.38,5.74] (6.46,6.82] (5.38,5.74] (5.74,6.1] (6.1,6.46] (5.38,5.74] [71] (5.74,6.1] (5.74,6.1] (6.1,6.46] (5.74,6.1] (6.1,6.46] (6.46,6.82] (6.46,6.82] (6.46,6.82] (5.74,6.1] (5.38,5.74] [81] (5.38,5.74] (5.38,5.74] (5.74,6.1] (5.74,6.1] (5.38,5.74] (5.74,6.1] (6.46,6.82] (6.1,6.46] (5.38,5.74] (5.38,5.74] [91] (5.38,5.74] (5.74,6.1] (5.74,6.1] (4.66,5.02] (5.38,5.74] (5.38,5.74] (5.38,5.74] (6.1,6.46] (5.02,5.38] (5.38,5.74] [101] (6.1,6.46] (5.74,6.1] (6.82,7.18] (6.1,6.46] (6.46,6.82] (7.54,7.9] (4.66,5.02] (7.18,7.54] (6.46,6.82] (7.18,7.54] [111] (6.46,6.82] (6.1,6.46] (6.46,6.82] (5.38,5.74] (5.74,6.1] (6.1,6.46] (6.46,6.82] (7.54,7.9] (7.54,7.9] (5.74,6.1] [121] (6.82,7.18] (5.38,5.74] (7.54,7.9] (6.1,6.46] (6.46,6.82] (7.18,7.54] (6.1,6.46] (5.74,6.1] (6.1,6.46] (7.18,7.54] [131] (7.18,7.54] (7.54,7.9] (6.1,6.46] (6.1,6.46] (5.74,6.1] (7.54,7.9] (6.1,6.46] (6.1,6.46] (5.74,6.1] (6.82,7.18] [141] (6.46,6.82] (6.82,7.18] (5.74,6.1] (6.46,6.82] (6.46,6.82] (6.46,6.82] (6.1,6.46] (6.46,6.82] (6.1,6.46] (5.74,6.1] 10 Levels: (4.3,4.66] (4.66,5.02] (5.02,5.38] (5.38,5.74] (5.74,6.1] (6.1,6.46] (6.46,6.82] (6.82,7.18] ... (7.54,7.9]
źródło
Kolejna sztuczka. Niektóre pakiety, jak glmnet, tylko przyjąć jako wejścia macierz projektowania i zmienną odpowiedzi. Jeśli ktoś chce dopasować model do wszystkich interakcji między cechami, nie może użyć formuły „y ~. ^ 2”. Używanie
expand.grid()
pozwala nam skorzystać z potężnego indeksowania tablic i operacji na wektorach R.interArray=function(X){ n=ncol(X) ind=expand.grid(1:n,1:n) return(X[,ind[,1]]*X[,ind[,2]]) } > X X1 X2 1 0.96852363 0.33827107 2 0.08012755 0.69159828 3 0.10167545 0.38119304 4 0.06699458 0.41756415 5 0.08187816 0.09805104 > interArray(X) X1 X2 X1.1 X2.1 1 0.938038022 0.327623524 0.327623524 0.114427316 2 0.006420424 0.055416073 0.055416073 0.478308177 3 0.010337897 0.038757974 0.038757974 0.145308137 4 0.004488274 0.027974536 0.027974536 0.174359821 5 0.006704033 0.008028239 0.008028239 0.009614007
źródło
model.matrix
?Jedną z moich ulubionych, jeśli nie nieco niekonwencjonalnych sztuczek, jest użycie
eval()
iparse()
. Ten przykład może być ilustracją tego, jak może to być pomocneNY.Capital <- 'Albany' state <- 'NY' parameter <- 'Capital' eval(parse(text=paste(state, parameter, sep='.'))) [1] "Albany"
Tego typu sytuacje zdarzają się częściej niż nie, a wykorzystanie
eval()
iparse()
może pomóc w rozwiązaniu tego problemu. Oczywiście cieszę się z wszelkich opinii na temat alternatywnych sposobów kodowania tego.źródło
set.seed()
ustawia stan generatora liczb losowych.Na przykład:
> set.seed(123) > rnorm(1) [1] -0.5604756 > rnorm(1) [1] -0.2301775 > set.seed(123) > rnorm(1) [1] -0.5604756
źródło
Dla tych, którzy piszą C, aby zadzwonić z R:
.Internal(inspect(...))
jest przydatne. Na przykład:> .Internal(inspect(quote(a+2))) @867dc28 06 LANGSXP g0c0 [] @8436998 01 SYMSXP g1c0 [MARK,gp=0x4000] "+" @85768b0 01 SYMSXP g1c0 [MARK,NAM(2)] "a" @8d7bf48 14 REALSXP g0c1 [] (len=1, tl=0) 2
źródło
d = '~ / R Kod / Biblioteka /'
files = list.files (d, '. r $')
for (f in files) {if (! (f == 'mysource.r')) {print (paste ('Sourcing', f)) source (paste (d, f, sep = ''))}}
Używam powyższego kodu do pozyskiwania wszystkich plików w katalogu podczas uruchamiania z różnymi programami narzędziowymi, których używam podczas mojej sesji interaktywnej z R. Jestem pewien, że są lepsze sposoby, ale uważam, że jest to przydatne w mojej pracy. Linia, która to robi, jest następująca.
źródło („~ / R Code / Library / mysource.r”)
źródło
Wykonywanie operacji na wielu zmiennych w ramce danych. To zostało skradzione z subset.data.frame.
get.vars<-function(vars,data){ nl <- as.list(1L:ncol(data)) names(nl) <- names(data) vars <- eval(substitute(vars), nl, parent.frame()) data[,vars] #do stuff here } get.vars(c(cyl:hwy,class),mpg)
źródło
get.vars
bez przeskakiwania przez całą masę kółek.Opublikowałem to już raz, ale używam go tak często, że pomyślałem, że opublikuję go ponownie. To tylko niewielka funkcja zwracająca nazwy i numery pozycji ramki data.frame. Nie jest to nic specjalnego, ale prawie nigdy nie przechodzę przez sesję bez wielokrotnego korzystania z niej.
##creates an object from a data.frame listing the column names and location
namesind = function (df) {
temp1=names(df) temp2=seq(1,length(temp1)) temp3=data.frame(temp1,temp2) names(temp3)=c("VAR","COL") return(temp3) rm(temp1,temp2,temp3)
}
ni <- namesind
źródło
data.frame(VAR = names(df), COL = seq_along(df))