En kullanışlı R numarası nedir? [kapalı]


88

Daha fazla ipucu ve püf noktası paylaşmak için R ile ilgili, en kullanışlı özelliğiniz veya numaranız nedir? Akıllı vektörleştirme? Veri girişi / çıkışı? Görselleştirme ve grafikler? İstatistiksel analiz? Özel fonksiyonlar? Etkileşimli ortamın kendisi?

Gönderi başına bir öğe ve oylarla kazanan olup olmayacağımızı göreceğiz.

[Edit 25-Aug 2008]: Yani bir hafta sonra, basit str()olan anketi kazandı. Ben de bunu tavsiye etmeyi sevdiğim için, kabul etmesi kolay bir cevap.


8
@Dirk: "topluluk wiki", "topluluğa ait" anlamına gelir, "anket sorusu" ile eşanlamlı değildir. Topluluk wiki polisini dinlemeyin.
Juliet


8
CW yine zorbalık. : Ben meta-so görmek ve yükseltirim meta.stackexchange.com/questions/392/...
ars

13
@ars: Kesin bir cevabı olmayan bir soru . Ergo CW yap.
dmckee --- eski moderatör kedicik

2
@JD Long komik yorum. maalesef perdenin arkasına gizlenmişti. Demek istediğim, zor R sorularını yanıtlamak, yığın halinde gerçekten işe yaramaz. Bu yüzden haritaya R'yi koyan güzel sorular soranların sonunda biraz itibar kazanması benim için sorun değil. Ayrıca bu, R kullanıcıları için kesinlikle C programcıları için en sevdiğiniz C hile sorusunun ne olacağından daha yararlıdır ...
Matt Bannert

Yanıtlar:


64

str() size herhangi bir nesnenin yapısını söyler.


Python kullanır dir()- daha mantıklı.
Hamish Grubijan

17
Ah, birçok dilde strkısaltmasıdır string.
Hamish Grubijan

Neden olmasın class()? Benzer türde bilgileri açığa çıkarıyor gibi görünüyor. Neden bu kadar benzer iki komut var?
hhh

1
class()str()görüntülenen bilgilerin sadece küçük bir kısmı
hadley

64

Sık kullandığım çok kullanışlı bir işlev, bir nesneyi R kodu biçiminde dökmenize izin veren dput () işlevidir.

# 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")

Yardım istediğinizde veya bir faktörün düzeylerini düzenlemek veya yeniden sıralamak istediğinizde kolayca yeniden üretilebilir veri yığınları göndermek çok yararlı olabilir.


42

head () ve tail () bir veri çerçevesinin, vektörün, matrisin, fonksiyonun vb. ilk ve son bölümlerini almak için. Özellikle büyük veri çerçevelerinde, bu, düzgün yüklendiğini kontrol etmenin hızlı bir yoludur.


38

Güzel bir özellik: Verileri okumak bağlantıları kullanır , yerel dosyalar, http aracılığıyla erişilen uzak dosyalar, diğer programlardan borular veya daha fazlası olabilen .

Basit bir örnek olarak, random.org'dan min = 100 ve max = 200 arasındaki N = 10 rastgele tamsayı için bu erişimi düşünün (bu, sözde rastgele sayı üreteci yerine atmosferik gürültüye dayalı gerçek rastgele sayılar sağlar):

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>

Bir kenara, random paketi, random.org'a erişmek için çeşitli kolaylık fonksiyonları sağlar .


BTW-- (1) bunları hemen yayınlarsanız ve (2) CW sorusunu sormazsanız , kendi kendine yanıtlar CW yapmanızı öneririm. Aksi takdirde, rep sistemini oynamaya çalışıyormuşsunuz gibi görünüyor. YMMV ve hepsi.
dmckee --- eski moderatör kedi yavrusu

1
Sistemi kandırmak değil, sadece işleri başlatmak. Hâlâ başka bir cevabı kabul etmekte özgür.
ars

2
@ars: Bunu kabul etmekte özgür. Tavsiyeme uymazsa onu wiki yapmaya da zorlamayacağım. Ancak hazırlanmış bir özyanıtı wiki olarak işaretlemeden yayınlamayacağım ve o olmadan da oy vermeyeceğim. Değeri neyse onu al.
dmckee --- eski moderatör yavru kedi

4
@Dirk: Jeff ve Joel tarafından kendi sorunuzu yanıtlamanız tamamen kabul edilebilir. Cevabınızı CW yapmak için HİÇBİR gereklilik, gayri resmi bile yoktur. Açıkça sistemi kandırmıyorsun. Bir kez daha, topluluk wiki polisini görmezden gelin.
Juliet

8
Sitelerin amacının bir kısmının genel sorunlar için en iyi yanıtları ve genel bir kaynak sağlamak olduğunu kabul etmeliyim. Soru sormak ve iyi bir cevap vermek bir konuyu desteklemeye yardımcı olabilir. Bu özellikle R. gibi yeni / küçük etiketler için kullanışlıdır.
kpierce8

35

Kullandığımı with()ve within()daha fazlasını buluyorum . Artık $kodumu karıştırmak yok ve birinin arama yoluna nesne eklemeye başlamasına gerek yok. Daha ciddisi, veri analizi komut dosyalarımın amacınıwith() vb. Daha net buluyorum .

> 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()R ifadesinin değerlendirildiği bir ortam kurar. within()aynı şeyi yapar ancak ortamı yaratmak için kullanılan veri nesnesini değiştirmenize izin verir.

> 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

İlk kullanıldığı zaman fark etmedi şey within()sen değerlendirilen ifadenin parçası olarak atama yapmak zorunda olduğunu ve istenen etkiyi elde etmek için (yukarıdaki gibi) iade nesneyi atar.


34

Veri Giriş numarası = RGoogleDocs paketi

http://www.omegahat.org/RGoogleDocs/

Google e-tablolarını tüm ortak çalışanların aynı sayfada olmasının harika bir yolu olarak buldum. Ayrıca, Google Formlar, yanıtlayanlardan gelen verileri almanıza ve bunları zahmetsizce bir google e-tablosuna yazmanıza olanak tanır. Veriler sık ​​sık değiştiğinden ve neredeyse hiçbir zaman nihai olmadığından, R'nin csv dosyalarını indirip okuyarak futz yerine doğrudan bir google elektronik tablosunu okuması çok daha tercih edilir.

# Get data from google spreadsheet
library(RGoogleDocs)
ps <-readline(prompt="get the password in ")
auth = getGoogleAuth("me@gmail.com", 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)

Aşağıdaki komutlardan birinin veya ikisinin birkaç saniye sürdüğünü hatırlayamıyorum.

  1. getGoogleAuth

  2. getGoogleDocsConnection

  3. getWorksheets


27

Standart olmayan adlara referans vermek için ters tikleri kullanın.

> 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

Bu durumda, df [, "1"] de işe yarar. Ancak geri işaretler formüllerin içinde çalışır!

> lm(`2`~`1`,data=df)

Call:
lm(formula = `2` ~ `1`, data = df)

Coefficients:
(Intercept)          `1`  
     0.4087      -0.3440  

[Düzenle] Dirk neden geçersiz isimler verileceğini soruyor? Bilmiyorum! Ancak bu problemle pratikte oldukça sık karşılaşıyorum. Örneğin, hadley'in yeniden şekillendirme paketini kullanarak:

> 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

Tamam, ama neden sözdizimsel olarak geçerli isimleri (x veya y gibi) ters işaret gerektiren geçersiz isimlerle (1 veya 2 gibi) değiştirmeniz gerekir?
Dirk Eddelbuettel

3
Ayrıca yanlış read.tableolduğunda check.names- yani orijinal sütun isimleriyle çalışmak istediğinizde de yararlıdır .
hadley

25

Bunun ne kadar iyi bilindiğini / bilmediğini bilmiyorum, ancak kesinlikle faydalandığım bir şey, ortamların geçiş-referans yetenekleridir.

zz <- new.env()
zz$foo <- c(1,2,3,4,5)
changer <- function(blah) {
   blah$foo <- 5
}
changer(zz)
zz$foo

Bu örnek için, bunun neden yararlı olacağı bir anlam ifade etmiyor, ancak etrafından büyük nesneler geçiriyorsanız yardımcı olabilir.


23

En sevdiğim yeni şey foreach kütüphanesi. Tüm güzel uygulamaları yapmanızı sağlar, ancak biraz daha kolay bir sözdizimi ile:

list_powers <- foreach(i = 1:100) %do% {
  lp <- x[i]^i
  return (lp)
}

En iyi yanı, gerçekten önemli miktarda zaman gerektiren bir şey yapıyorsanız , bir küme genelinde bile anında paralel hale getirmek %do%için %dopar%(uygun arka uç kitaplığıyla) arasında geçiş yapabilirsiniz . Çok şık.


19

Verilerin birçok temel işleyişini yapıyorum , işte günlük kullandığım iki yerleşik işlev ( dönüştürme , alt küme ) ve bir kitaplık ( sqldf ).

örnek satış verileri oluşturun

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

sütun eklemek için transform () kullanın

## 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
...

verileri dilimlemek için subset () kullanın

subset(sales, 
       country == 'USA' & product %in% c(1, 2), 
       select = c('product', 'revenue'))

>
  product  revenue
1       1 108.4597
4       2 100.3475

SQL ile dilimlemek ve toplamak için sqldf () kullanın

Sqldf paketi R veri çerçeveleri için bir SQL arabirimi sağlar

##  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

Bir toplama veya GROUP BY gerçekleştirin

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

Veri çerçevelerinde daha karmaşık harita azaltma benzeri işlevsellik için plyr paketine göz atın . Ve kendinizi saçınızı çekmek isterken bulursanız , R ile Veri Manipülasyonunu kontrol etmenizi öneririm .


18
?ave

"X []" alt kümelerinin ortalaması alınır, burada her alt küme aynı faktör seviyelerine sahip gözlemlerden oluşur. Kullanım: ave (x, ..., EĞLENCE = ortalama)

Ben her zaman kullanırım. (örneğin bu cevapta burada öyle )


bunun tapply'den (x, faktör, eğlence) farkı nedir?
TMS

1
@Tomas ave sıralamayı ve uzunluğu korur. böylece, örneğin, bir veri kümesine grup araçlarının vektörünü tek adımda ekleyebilirsiniz.
Eduardo Leoni

18

Kodu hızlandırmanın ve döngüleri ortadan kaldırmanın bir yolu.

değerleri arayan bir veri çerçevesi boyunca döngü yapan döngüleri yerine. sadece bu değerlerle df'nin bir alt kümesini çok daha hızlı alın.

yani bunun yerine:

for(i in 1:nrow(df)){
  if (df$column[i] == x) {
    df$column2[i] <- y
    or any other similiar code
  }
}

bunun gibi bir şey yapın:

df$column2[df$column1 == x] <- y

bu temel kavram son derece sık uygulanabilir ve döngüleri ortadan kaldırmanın harika bir yoludur


11
Burada beni sürekli yakalayan küçük bir tuzak var. Df $ sütun1 NA değerleri içeriyorsa, == kullanarak alt küme oluşturma, x'e ve herhangi bir NA'ya eşit olan tüm değerleri çıkarır . Bunu önlemek için, "==" yerine "% in%" kullanın.
Matt Parker

Matt kesinlikle haklısın ve bu nefret ettiğim bir şey, yine de yöntemini beğendim. Genelde sütunu NA'lar için kontrol ediyorum ve daha sonra bunları bir veri çerçevesi sütununu alan ve veri çerçevesi eksi satırları yalnızca o sütunda NA'larla döndüren hızlı bir işlevle kaldırıyorum.
Dan

Esasen, bir veri çerçevesini değerlere sahip olmam gereken sütunlara indirgiyorum, sonra doğru satırları elde etmek için na.omit'i kullanıyorum ve ardından orijinal veri kümesini yalnızca bu satırlarla alt kümelendiriyorum. Sadece na.omit kullanmak herhangi bir NA ile herhangi bir satırı kaldırırdı, yine de yanılmış olabilirim.
Dan

16

Bazen rbindbirden çok veri çerçevesine ihtiyaç duyarsınız . do.call()bunu yapmanıza izin verecek (bind bu soruyu sorduğumda birisi bana bunu açıklamak zorunda kaldı, çünkü bariz bir kullanım gibi görünmüyor).

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)

İyi arama: Bunun genellikle kullanmaktan daha basit olduğunu görüyorum unsplit .
Richie Cotton

16

R programlama (değil etkileşimli oturumlar), ben kullanmak if (bad.condition) stop("message")bir sürü . Her işlev bunlardan birkaçıyla başlar ve hesaplamalarla çalışırken bunları da içine alırım. Sanırım assert()C'de kullanmayı alışkanlık haline getirdim . Faydalar iki yönlüdür. Birincisi, bu kontrolleri yerine getirerek çalışma kodu almak çok daha hızlıdır. İkincisi ve muhtemelen daha da önemlisi, düzenleyicinizin her ekranında bu kontrolleri gördüğünüzde mevcut kodla çalışmak çok daha kolaydır. Merak etmek zorunda kalmayacaksınız x>0ya da öyle olduğunu belirten bir yoruma güvenmeniz gerekmeyecek ... bir bakışta öyle olduğunu anlayacaksınız .

PS. Buradaki ilk yazım. Nazik olmak!


12
Kötü bir alışkanlık değil ve R daha başka bir yol sunuyor: stopfifnot(!bad.condition)bu daha özlü.
Dirk Eddelbuettel

13

traceback()Eğer bir hata bir yere sahiptir ve kolayca bunu anlamıyorum zaman fonksiyonu bir zorunluluktur. Yığının bir izini basacaktır, çünkü R varsayılan olarak çok ayrıntılı değildir.

Sonra ayar options(error=recover) , hatayı artıran işleve "girmenize" ve tam olarak ne olduğunu anlamanıza ve sanki onun üzerinde tam kontrole sahipseniz ve ona bir koyabilirmişsiniz gibi tam olarak ne olduğunu anlamanıza izin verecektir browser().

Bu üç işlev, kodunuzda hata ayıklamaya gerçekten yardımcı olabilir.


1
options(error=recover)benim favori hata ayıklama yöntemim.
Joshua Ulrich

12

Hiç kimsenin başvuru, tapply, lapply ve sapply hakkında paylaşım yapmamasına gerçekten şaşırdım. R'de bir şeyler yaparken kullandığım genel bir kural, veri işleme veya simülasyonlar yapan bir for döngüsüne sahipsem, onu çarpanlarına ayırmaya ve bir * apply ile değiştirmeye çalışmamdır. Bazı insanlar * uygulama işlevlerinden çekiniyorlar çünkü yalnızca tek parametreli işlevlerin aktarılabileceğini düşünüyorlar. Hiçbir şey gerçeğin ötesinde olamaz! Javascript'te birinci sınıf nesneler olarak parametrelerle işlevler arasında geçiş yapmak gibi, bunu R'de anonim işlevlerle yaparsınız. Örneğin:

 > 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"

(#Rstats'i takip edenler için bunu da oraya gönderdim).

Unutmayın, apply, sapply, lapply, tapply ve do.call'ı kullanın! R'nin vektörleştirmesinden yararlanın. Asla bir grup R koduna doğru yürüyüp şunu görmemelisiniz:

N = 10000
l = numeric()
for (i in seq(1:N)) {
    sim <- rnorm(1, 0, 1)
    l <- rbind(l, sim)
}

Bu sadece vektörize edilmez, aynı zamanda R'deki dizi yapısı Python'da olduğu gibi büyütülmez (alan bittiğinde boyut iki katına çıkar, IIRC). Bu nedenle, her bir ciltleme adımı önce rbind () 'den gelen sonuçları kabul edecek kadar büyümeli, ardından önceki l'nin içeriğinin tamamını kopyalamalıdır. Eğlenmek için yukarıdakileri R'de deneyin. Ne kadar sürdüğüne dikkat edin (Rprof'a veya herhangi bir zamanlama fonksiyonuna bile ihtiyacınız olmayacak). O zaman dene

N=10000
l <- rnorm(N, 0, 1)

Aşağıdakiler de ilk versiyondan daha iyidir:

N = 10000
l = numeric(N)
for (i in seq(1:N)) {
    sim <- rnorm(1, 0, 1)
    l[i] <- sim
}

uygula, sapply, lapply ve tapply kullanışlıdır. Round gibi adlandırılmış bir işleve parametre iletmek istiyorsanız, anonim bir işlev yazmak yerine bunu uygula ile birlikte iletebilirsiniz. "[1] -0.29 0.29 1.31 -0.06 -1.90 -0.84 0.21 0.02 0.23 -1.10" sonucunu veren "sapply (rnorm (10, 0, 1), round, digits = 2)" deneyin.
Daniel

11

Dirk'in tavsiyesi üzerine, tek örnekler veriyorum. Umarım bu seyirci için çok "sevimli" [zeki, ama umurumda değil] veya önemsiz değillerdir.

Doğrusal modeller R'nin özüdür. Bağımsız değişkenlerin sayısı yüksek olduğunda, birinin iki seçeneği vardır. Birincisi, Matlab'a benzer şekilde, tasarım matrisi x'i ve y yanıtını bağımsız değişken olarak alan lm.fit () kullanmaktır. Bu yaklaşımın dezavantajı, dönüş değerinin nesnelerin bir listesi olması (yerleştirilmiş katsayılar, artıklar, vb.), Güzel bir şekilde özetlenebilen, tahmin, aşamalı seçim vb. İçin kullanılabilen "lm" sınıfına ait bir nesne değil. yaklaşım bir formül oluşturmaktır:

> 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  

Her gönderi için bir tane seçip bir örnekle anlatmaya ne dersiniz? Daha sonra günlerce devam edebilir ve yeni komutlarla yeni örnekler gönderebiliriz ... [BTW: Hatırladığım kadarıyla, formül kullanımı için as.formula (paste (...)) ihtiyacınız var. ]
Dirk Eddelbuettel

"Y ~. - 1" biçimi kapsadığı için tüm sütunları kaplamak için açıkça formül oluşturmanıza gerek yoktur. "." 'Bağımlı değişken dışındaki tüm sütunlar' anlamına gelir ve '- 1', örneğinizdeki gibi sabiti hariç tutar.
Dirk Eddelbuettel

Bu belirli örnek için doğru, ancak ncols >> sıralı X için, özellikle analizin son aşamalarında, genellikle bazı bağımsız değişkenleri kaldırırım. Bu durumda, veri çerçevesi adlarından bir formül oluşturmak hala kullanışlıdır.
gappy

10

If-else bloğundan dönen bir değer atayabilirsiniz.

Bunun yerine, örneğin

condition <- runif(1) > 0.5
if(condition) x <- 1 else x <- 2

yapabilirsin

x <- if(condition) 1 else 2

Bunun tam olarak nasıl çalıştığı derin bir sihirdir.


6
Bunu x <- ifelse (koşul, 1, 2) gibi de yapabilirsiniz, bu durumda her bileşen vektörleştirilir.
Shane

Shane, yapabilirsin, ama ifelse () ne yaparsa derinden sarkmadıkça, muhtemelen yapmamalısın! Yanlış anlaşılması kolay ...
Harlan

Bunda büyülü olan ne? Sadece yol Yani if-then-elseifadeleri herhangi fonksiyonel dilde çalışacak (ile karıştırılmamalıdır if-then-else ifadeleri ). ?:C benzeri dillerin üçlü operatörüne çok benzer .
Frank

10

R'ye tam bir çaylak ve istatistiklerde bir acemi olarak unclass() , bir veri çerçevesinin tüm öğelerini sıradan bir liste olarak yazdırmayı seviyorum .

Olası sorunları hızla göze almak için eksiksiz bir veri kümesine bir arada bakmak için oldukça kullanışlıdır.


9

CrossTable()dan gmodelspaketin olağan testler (Chisq, McNemar vs.) ile birlikte Sas- ve SPSS tarzı Crosstabs kolay erişim sağlar. Temel olarak, xtabs()fantezi çıktı ve bazı ek testler ile - ancak çıktıları kutsallarla paylaşmayı kolaylaştırıyor.


Güzel!! Biraz gmodel kullanıyorum, ancak bunu kaçırdım
Abhijit

İyi cevap, beni dinsizlerle aşırı tablo açıklamasından alıkoyacak her şey, zamanı iyi kullanmaktır.
Stedy

7

Kesinlikle system(). R ortamının içinden tüm unix araçlarına (en azından Linux / MacOSX altında) erişebilmek, günlük iş akışımda hızla paha biçilmez hale geldi.


1
Bu, bağlantılar hakkındaki önceki yorumuma bağlanır: ayrıca, verileri Unix komutlarından veya bunlara aktarmak için pipe () kullanabilirsiniz. help(connections)Ayrıntılar ve örnekler için bakın .
Dirk Eddelbuettel

6

İşte bir faktörü sayısal hale dönüştürmek için can sıkıcı bir çözüm. (Diğer veri türleri için de benzer)

old.var <- as.numeric(levels(old.var))[as.numeric(old.var)]

2
Belki de "karakter sahibi" vektörünü kastettiniz. Bu durumda "as.character (old.var)" daha basittir.
Dirk Eddelbuettel

1
Her zaman bu tavsiyenin (? Faktöründe okunabilir) yanlış yönlendirilebileceğini düşünmüşümdür. Old.var'ın bir faktör olduğundan emin olmalısınız ve bu, R oturumu için belirlediğiniz seçeneklere göre değişecektir. As.numeric (as.character (old.var)) kullanmak hem daha güvenli hem de daha temizdir.
Eduardo Leoni

Gerçekten olumsuz oy vermeye değmez, ama her neyse. Bu benim için çalışıyor.
Ryan R. Rosario

Ryan - Kodunuzu düzeltebilir misiniz? Old.var <- faktör (1: 2) ise; kodunuz [1] "1" "2" (sayısal değil) verecektir. Belki de demek istediniz.numeric (level (old.var) [old.var])?
Eduardo Leoni

3
Ya da biraz daha verimli:as.numeric(levels(old.var))[old.var]
hadley

6

Bu soru bir süredir sorulsa da, kısa süre önce SAS ve R blogunda komutu kullanmak için harika bir numara keşfettim cut. Komut, verileri kategorilere ayırmak için kullanılır ve iris veri setini örnek olarak kullanacağım ve 10 kategoriye ayıracağım:

> 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]

5

Başka bir numara. Glmnet gibi bazı paketler, yalnızca tasarım matrisini ve yanıt değişkenini girdi olarak alır. Özellikler arasındaki tüm etkileşimleri bir modele uydurmak isterse, "y ~. ^ 2" formülünü kullanamaz. Kullanımı expand.grid(), R'nin güçlü dizi indekslemesinden ve vektör işlemlerinden yararlanmamızı sağlar.

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

3
Bir modelleme işlevi bir formülü kabul etmiyorsa (ki bu çok nadirdir!), Tasarım matrisini oluşturmak daha iyi olmaz mıydı model.matrix?
hadley

Güzel bir. Bu işlevin varlığını bilmiyordum. Yukarıdaki işlev, model.matrix (~. ^ 2 -1, X) ile eşdeğerdir. Ancak matrisleri geçirme konusunda, glmnet'in yanı sıra, dizi işaretçilerini özel C işlevlerine geçirmem benim için sık sık görülür. Aslında, bir formülü bir işleve nasıl geçireceğimi bilemezdim. Oyuncak örneğiniz var mı?
gappy

5

Benim favorim, aynı biraz alışılmışın dışında değil hileler eğer kullanılmasıdır eval()ve parse(). Bu örnek belki de nasıl yardımcı olabileceğini gösteriyor

NY.Capital <- 'Albany'
state <- 'NY'
parameter <- 'Capital'
eval(parse(text=paste(state, parameter, sep='.')))

[1] "Albany"

Bu tür bir durum, sık olmamakla birlikte daha sık meydana gelir ve bunların kullanımı eval()ve bunların parse()ele alınmasına yardımcı olabilir. Elbette, bunu kodlamanın alternatif yolları hakkında herhangi bir geri bildirim almaktan memnuniyet duyarım.


1
Bu, adlandırılmış vektör öğeleriyle de yapılabilir.
Dirk Eddelbuettel

3
library (fortunes); fortune (106) Cevap parse () ise, genellikle soruyu yeniden düşünmelisiniz. - Thomas Lumley R-help (Şubat 2005)
Eduardo Leoni

İşte eval () ve parse () 'nin yararlı olabileceği bir örnek. Bu, bir Bioconductor paketi içerir, örneğin hgu133a.db ve bir prob seti kimliği hakkında çeşitli bilgi parçalarını almaya çalıştığınız yer. Örneğin: library (hgu133a.db) parametresi <- 'SYMBOL' mget ('202431_s_at', env = eval (parse (text = paste ('hgu133a', parameter, sep = '')))) parametre <- 'ENTREZID 'mget (' 202431_s_at ', env = eval (parse (text = paste (' hgu133a ', parameter, sep =' '))))
andrewj

Dirk'in dediği gibi, bu, adlandırılmış vektör öğeleriyle veya `` get (paste (state, parameter, sep = '.'))
İle

@Hadley, bu şekilde get () kullanabileceğini bilmiyordum. Teşekkürler.
andrewj

5

set.seed() rastgele sayı üreteci durumunu ayarlar.

Örneğin:

> set.seed(123)
> rnorm(1)
[1] -0.5604756
> rnorm(1)
[1] -0.2301775
> set.seed(123)
> rnorm(1)
[1] -0.5604756

rastgele işlevler kullanan örneklerle çok kullanışlıdır ... herkesin aynı sayfaya
JD Long

5

C yazanlar için R'den .Internal(inspect(...))aranmak kullanışlıdır. Örneğin:

> .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

4

d = '~ / R Kodu / Kitaplık /'

dosyalar = list.files (d, '. r $')

for (f dosyalarda) {if (! (f == 'mysource.r')) {print (paste ('Sourcing', f)) source (paste (d, f, sep = ''))}}

R ile etkileşimli oturumumda kullandığım çeşitli yardımcı programlarla başlangıçta bir dizindeki tüm dosyaları kaynaklamak için yukarıdaki kodu kullanıyorum. Eminim daha iyi yollar vardır, ancak işim için yararlı buluyorum. Bunu yapan satır aşağıdaki gibidir.

kaynak ("~ / R Kodu / Kitaplık / mysource.r")


6
Yapma. Bir paket yazın.
Dirk Eddelbuettel

Teşekkürler. Roxygen ile ilgili bir veya iki konuya bakıyordum ve görünüşe göre basit bir kendi kendine kullanım paketi yazmayı denemem gereken seviyedeyim.
mcheema

3

Bir veri çerçevesindeki bir dizi değişken üzerinde işlem gerçekleştirmek için. Bu, subset.data.frame'den çalındı.

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)

1
Bu ilk bakışta havalı görünebilir, ancak bu tür bir kod uzun vadede sorun yaşamamanıza neden olmaz. Açık olmak her zaman daha iyidir.
hadley

Hum, bu numarayı son zamanlarda epeyce kullanıyorum. Sınırsız sorunu hakkında daha net konuşabilir misiniz?
Ian Fellows

Belki Hadley bunun yerine Plyr paketini kullanmayı öneriyordur?
Christopher DuBois

3
Hayır, bunun yerine plyr kullanmak için üstü kapalı bir öneri değil. Kodunuzla ilgili temel sorun, anlamsal olarak tembel olmasıdır - kullanıcıya ne istediğini açıkça söyletmek yerine, tahmin etmek için biraz "sihir" yaparsınız. Bununla ilgili sorun, fonksiyonun programlanmasını çok zorlaştırmasıdır - yani, get.varsçok sayıda çembere atlamadan çağıran bir fonksiyon yazmak zordur .
hadley

3

Bunu daha önce bir kez gönderdim ama o kadar çok kullanıyorum ki, tekrar göndereceğimi düşündüm. Bir data.frame'in isimlerini ve konum numaralarını döndürmek için sadece küçük bir işlev. Emin olmak için özel bir şey değil, ama bir seansta neredeyse hiç kullanmıyorum.

##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


4
Bu gerçekten tek data.frame(VAR = names(df), COL = seq_along(df))
satırlık bir

çok şık, belki onu ni <- function (df) {data.frame (VAR = names (df), COL = seq_along (df))}
kpierce8

1
Kullanıyorum: data.frame (colnames (the.df))
Tal Galili
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.