最も便利なRトリックは何ですか?[閉まっている]


88

Rに関するいくつかのヒントとコツを共有するために、最も便利な機能またはコツは何ですか?賢いベクトル化?データ入出力?視覚化とグラフィックス?統計分析?特別な機能?インタラクティブ環境自体?

投稿ごとに1つのアイテム。投票によって勝者を獲得できるかどうかを確認します。

[2008年8月25日編集]:したがって、1週間後、単純str()投票が投票に勝ったようです。私自身もそのことをお勧めしたいので、受け入れるのは簡単です。


8
@Dirk:「コミュニティウィキ」は「コミュニティ所有」を意味し、「投票問題」の同義語ではありません。コミュニティウィキポリスに耳を傾けないでください。
ジュリエット

4
meta.stackexchange.com/questions/11740/…を考慮すると、CWである必要があります。
dmckee ---元モデレーターの子猫

8
CWいじめ。私はあなたのメタ-SOを見て、あなたを上げるでしょう:meta.stackexchange.com/questions/392/...
ARS

13
@ars:明確な答えがない質問です。エルゴはそれをCWにします。
dmckee ---元モデレーターの子猫

2
@JD長い陽気なコメント。残念ながら、それは折り目に隠されていました。難しいRの質問に答えても、実際にはスタック担当者の利益にはなりません。ですから、Rをマップに載せる素敵な質問を設定した人たちが最終的にクレジットを獲得できれば、私には問題ありません。このほかに...あなたの好きなCのトリックの質問は、Cプログラマになりwhat'sよりも、確かにRのユーザーがより便利である
マットBannert

回答:


64

str() オブジェクトの構造を示します。


Pythonの使用dir()-より理にかなっています。
Hamish Grubijan

17
ああ、多くの言語strstringは略語です。
Hamish Grubijan、2010

なんでclass()?同様のタイプの情報を明らかにするようです。なぜこのようなコマンドが2つあるのですか?
hhh

1
class()str()表示される情報のほんの一部です
ハドリー

64

私がよく使用する便利な関数の1つはdput()です。これを使用すると、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")

助けを求めるときに簡単に再現できるデータチャンクを投稿したり、因子のレベルを編集または並べ替えたりすることは非常に便利です。


42

head()およびtail()を使用して、データフレーム、ベクトル、行列、関数などの最初と最後の部分を取得します。特に、大きなデータフレームの場合、これはロードが正常に行われたことを確認する簡単な方法です。


38

1つの優れた機能:データの読み取りは、ローカルファイル、http経由でアクセスされるリモートファイル、他のプログラムからのパイプなどの接続を使用します。

簡単な例として、random.orgからのmin = 100からmax = 200までのN = 10のランダムな整数へのアクセスを考えます(擬似乱数ジェネレーターではなく、大気ノイズに基づいた真の乱数を提供します)。

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>

余談ですが、randomパッケージはrandom.orgにアクセスするためのいくつかの便利な関数を提供します。


BTW--私はあなたがすることをお勧めしたいはずですあなたは速やかにそれらを投稿し、(2)あなたが質問CWをしない(1)場合selfanswers CWを作ります。それ以外の場合は、担当者システムをゲームしようとしているように見えます。YMMVなど。
dmckee ---元モデレーターの子猫

1
それはシステムのゲームではなく、物事を始めることです。彼はまだ他の答えを受け入れるのは自由です。
ARS

2
@ars:彼はこれを自由に受け入れます。彼が勝った場合、私は彼にそれをwikiに強制することを試みるつもりはありません;私のアドバイスを受けません。しかし、wikiにマークを付けずに準備済みの自己回答を投稿することはありません。また、それがないと自己回答にも投票しません。それは価値があるもののためにそれを取る。
dmckee ---元モデレーターの子猫

4
@Dirk:自分の質問に答えることは、ジェフとジョエルにすすめられても、まったく問題ありません。あなたの答えをCWにするための要件は、非公式なものでさえありません。あなたは明らかにシステムを賭けていません。繰り返しになりますが、コミュニティウィキポリスは無視してください。
ジュリエット

8
サイトの目的の一部は、一般的な問題と一般的なリソースに対する最良の回答を提供することであることに同意する必要があります。質問を投げかけ、適切な回答を提供することで、トピックを強化できます。これは、Rとして、新たな/小さなタグと特に便利です
kpierce8

35

私が使用しています見つけるwith()within()、より多くの。$私のコードを散らかすことはもうありません、そしてオブジェクトを検索パスにアタッチし始める必要はありません。もっと真剣に、私はデータ分析スクリプトの意図をより明確にwith()するなどを見つけました。

> 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式が評価される環境をセットアップします。within()同じことを行いますが、環境の作成に使用されるデータオブジェクトを変更できます。

> 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

私が最初に使用されたとき、私は実現しなかった何かがwithin()、あなたが評価された式の一部として割り当てをしなければならないということである所望の効果を得るために、(上記のように)返されたオブジェクトを割り当てます。


34

データ入力トリック= RGoogleDocsパッケージ

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

Googleスプレッドシートは、すべての共同編集者が同じページにいるための素晴らしい方法であることがわかりました。さらに、Googleフォームを使用すると、回答者からデータを取得して、Googleスプレッドシートに簡単に書き込むことができます。データは頻繁に変化し、ほとんど最終的なものではないため、csvファイルをダウンロードして読み込むことよりも、Rがgoogleスプレッドシートを直接読み取る方がはるかに望ましいです。

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

次のコマンドの1つまたは2つが数秒かかるのを思い出せません。

  1. getGoogleAuth

  2. getGoogleDocsConnection

  3. getWorksheets


27

標準ではない名前を参照するには、バックティックを使用します。

> 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

この場合、df [、 "1"]も機能​​します。しかし、バックティックは数式内で機能します。

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

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

Coefficients:
(Intercept)          `1`  
     0.4087      -0.3440  

[編集]ダークはなぜ無効な名前を付けるのかと尋ねる?知りません!しかし、私は確かにかなり頻繁にこの問題に出会います。たとえば、hadleyのreshapeパッケージを使用します。

> 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

わかりましたが、なぜ構文的に有効な名前(xやyなど)を、バッククォートを必要とする無効な名前(1や2など)に置き換える必要があるのでしょうか。
Dirk Eddelbuettel、2009

3
これはread.tablecheck.namesがfalseの場合、つまり元の列名を操作したい場合にも役立ちます。
ハドリー2009

25

これがどれほどよく知られている/知られていないかはわかりませんが、私が間違いなく利用したものは、環境の参照渡し機能です。

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

この例では、なぜそれが役立つのかは意味がありませんが、大きなオブジェクトを渡す場合は役立ちます。


23

私の新しいお気に入りはforeachライブラリです。それはあなたが素晴らしい適用のすべてを行うことを可能にしますが、やや簡単な構文で:

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

最良の部分は、実際にかなりの時間を必要とする何かを実行している場合%do%%dopar%(適切なバックエンドライブラリを使用して)からに切り替えて、クラスター全体でも瞬時に並列化できることです。とても滑らかです。


19

私は多くの基本的なデータ操作を行っているので、ここでは毎日使用する2つの組み込み関数(transformサブセット)と1つのライブラリー(sqldf)を示します。

サンプル販売データを作成する

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

列を追加するには、transform()を使用します

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

データをスライスするには、subset()を使用します

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

>
  product  revenue
1       1 108.4597
4       2 100.3475

sqldf()を使用して、SQLでスライスおよび集計する

sqldfパッケージは Rデータフレームに対してSQLインタフェースを提供します

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

集計または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

データフレームのより洗練されたmap-reduceのような機能については、plyrパッケージをチェックしてください。そして、自分の髪を引き出したいと思ったら、Rによるデータ操作をチェックすることをお勧めします。


18
?ave

'x []'のサブセットは平均化され、各サブセットは同じ因子水準の観測から構成されます。使用法:ave(x、...、FUN = mean)

いつも使っています。(例えば、この答えでここにそう


これはtapply(x、factor、fun)とどう違うのですか?
TMS 2011

1
@Tomas aveは、順序と長さを保持します。たとえば、グループ平均のベクトルを1つのステップでデータセットに追加できます。
エドゥアルドレオニ

18

コードを高速化してforループを排除する方法。

値を探すデータフレームをループするforループの代わりに。これらの値を使用してdfのサブセットを取得するだけで済みます。

代わりに:

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

次のようなことをしてください:

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

その基本概念は非常に頻繁に適用され、forループを取り除くための優れた方法です


11
ここにはいつも私を追いつけていた小さな罠があります。df $ column1にNA値が含まれている場合、==を使用してサブセット化すると、x および NAに等しい値がすべて取り出されます。これを回避するには、「==」の代わりに「%in%」を使用します。
マットパーカー、

マットはあなたが絶対に正しいと私は嫌いなものですが、私はあなたの方法が好きです。私は通常、列のNAをチェックしてから、データフレーム列を取得し、データフレームからその列にのみNAのある行を差し引いた行を返す、私が作成したクイック関数で列を削除します。
ダン、

基本的に、私は値を持つ必要がある列にデータフレームを分割し、na.omitを使用して正しい行を取得し、それらの行のみで元のデータセットをサブセット化します。na.omitを使用するだけで、NAのある行が削除されますが、誤解される可能性があります。
Dan、

16

場合によっては、rbind複数のデータフレームが必要になります。 do.call()あなたがそれをできるようにします(バインドが私にこの質問をしたとき、それが明白な使用ではないように見えるので、誰かが私にこれを説明しなければなりませんでした)。

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)

良い呼び出し:これは、を使用するよりも簡単であることがよくありunsplitます。
リッチーコットン

16

Rプログラミング(インタラクティブセッションではない)では、私if (bad.condition) stop("message")たくさん使用します。すべての関数はこれらのうちのいくつかから始まり、計算を進めながら、これらも実行します。私assert()はCでの使用から習慣になったと思います。メリットは2つあります。まず、これらのチェックを配置してコードを実行する方がはるかに高速です。2つ目は、おそらくより重要なことですが、エディターのすべての画面でこれらのチェックを確認すると、既存のコードを操作する方がはるかに簡単です。あなたは不思議にするかどうかを持っていないx>0、またはコメントをあなたはよ...それがあることを示す信頼を知って、それがあることを、一目から、。

PS。ここに私の最初の投稿。穏やかな!


12
悪い習慣ではありません、そしてRはさらに別の方法を提供します: stopfifnot(!bad.condition)より簡潔です。
Dirk Eddelbuettel

13

traceback()どこかでエラーが発生し、すぐに理解できない場合、この機能は必須です。Rはデフォルトでは非常に冗長ではないため、スタックのトレースを出力します。

次に、設定をoptions(error=recover)行うと、エラーを発生させる関数に「入る」ことができ、まるでそれを完全に制御できbrowser()、そこにを置くことができるかのように、何が起こっているのかを正確に理解できます。

これらの3つの関数は、コードのデバッグに役立ちます。


1
options(error=recover)私のお気に入りのデバッグ方法です。
ジョシュアウルリッヒ

12

apply、tapply、lapply、sapplyについて誰も投稿していないことに本当に驚いています。Rで物事を行うときに使用する一般的なルールは、データ処理またはシミュレーションを実行するforループがある場合、それを除外して* applyに置き換えようとすることです。一部の人々は、単一のパラメーター関数のみを渡すことができると考えているため、* apply関数を敬遠します。真実からそれ以上のものはありません!JavaScriptのファーストクラスオブジェクトとしてパラメーターを持つ関数を渡すように、Rでは匿名関数を使用してこれを行います。例えば:

 > 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をフォローしている人のために、私もこれを投稿しました)。

apply、sapply、lapply、tapply、do.callを使用してください。Rのベクトル化を活用します。Rコードの束まで歩いて見てはいけません。

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

これはベクトル化されないだけでなく、Rの配列構造はPythonのように拡張されません(スペースがなくなるとサイズが2倍になる、IIRC)。したがって、rbindの各ステップでは、まずrbind()の結果を受け入れるのに十分なだけlを大きくしてから、前のlの内容全体をコピーする必要があります。楽しみのために、上記のRを試してください。時間がかかることに注意してください(Rprofやタイミング関数も必要ありません)。次に試してください

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

以下も最初のバージョンよりも優れています:

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

apply、sapply、lapply、tapplyが便利です。ラウンドのような名前付き関数にパラメーターを渡したい場合は、無名関数を作成する代わりに、applyと一緒に渡すことができます。「[1] -0.29 0.29 1.31 -0.06 -1.90 -0.84 0.21 0.02 0.23 -1.10 "を出力する「sapply(rnorm(10、0、1)、round、digits = 2)」を試してください。
ダニエル

11

ダークの助言に基づいて、私は単一の例を投稿しています。彼らがあまりにも「かわいい」[賢いが、私は気にしない]またはこの聴衆にとってささいなことではないことを願っています。

線形モデルはRのパンとバターです。独立変数の数が多い場合、2つの選択肢があります。1つ目は、Matlabと同様に、設計行列xと応答yを引数として受け取るlm.fit()を使用することです。このアプローチの欠点は、戻り値がオブジェクト(適合係数、残差など)のリストであり、クラス "lm"のオブジェクトではないことです。これは、要約、予測、段階的選択などに使用できます。アプローチは式を作成することです:

> 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  

投稿ごとに1つ選び、例で説明するとどうでしょうか。その後、何日も続けて、新しいコマンドを使用して新しい例を投稿することができます... [ところで、私が覚えているように、式を使用するにはas.formula(paste(...))が必要です。]
Dirk Eddelbuettel、2009

"y〜。-1"の形式ですべての列をカバーするため、明示的に式を作成する必要はありません。「。」は、「従属変数を除くすべての列を意味し、「-1」は、例のように定数を除外します。
Dirk Eddelbuettel、2009

これはこの特定の例では正しいですが、ncols >> nrowsを使用するXの場合、特に分析の最終段階で、いくつかの独立変数を削除することがよくあります。この場合でも、データフレーム名から式を作成すると便利です。
ギャップの多い2009

10

if-elseブロックから返される値を割り当てることができます。

代わりに、例えば

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

できるよ

x <- if(condition) 1 else 2

これが正確にどのように機能するかは、深い魔法です。


6
x <-ifelse(condition、1、2)のようにこれを行うこともできます。その場合、各コンポーネントはベクトル化されます。
シェーン

シェーン、できますが、ifelse()が何をするのか本当に深く理解しない限り、おそらくすべきではありません!それは誤解しやすいものです...
Harlan

それの魔法は何ですか?これif-then-elseは、関数型言語で式が機能するための方法です(if-then-else ステートメントと混同しないでください)。?:C言語に似た言語の三項演算子によく似ています。
フランク

10

Rの初心者で、統計の初心者unclass() として、データフレームのすべての要素を通常のリストとして出力するのが大好きです。

完全なデータセットを1度に見て、潜在的な問題にすばやく目を向けるには、非常に便利です。


9

CrossTable()gmodelsパッケージからは、通常のテスト(Chisq、McNemarなど)とともに、SASおよびSPSSスタイルのクロス集計に簡単にアクセスできます。基本的には、xtabs()派手な出力といくつかの追加テストが含まれますが、異教徒との出力の共有が簡単になります。


いいね!私はかなりgmodelsを使用していますが、見落としました
Abhijit

良い答えです。異教徒とのテーブルの過度の説明から私を遠ざけることができるものは、時間の有効利用です。
Stedy

7

間違いなくsystem()。R環境内からすべてのUNIXツール(少なくともLinux / MacOSXのもとで)にアクセスできるようになることは、私の日常のワークフローにおいて急速に貴重なものになりました。


1
これは、接続についての以前のコメントと関連しています。また、pipe()を使用して、Unixコマンドとの間でデータをやり取りすることもできます。help(connections)詳細と例については、を参照してください。
Dirk Eddelbuettel、2009

6

因子を数値に変換するための迷惑な回避策を次に示します。(他のデータ型についても同様)

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

2
たぶん、あなたは「キャラケーターの中へ」のベクトルを意味しました。その場合、「as.character(old.var)」の方が簡単です。
Dirk Eddelbuettel、2009

1
私はいつもこのアドバイス(?factorで読むことができます)は誤ったものだと思っていました。old.varが要因であることを確認する必要があります。これは、Rセッションに設定したオプションによって異なります。as.numeric(as.character(old.var))を使用すると、安全かつクリーンになります。
Eduardo Leoni

本当に投票する価値はありませんが、何でも。これでうまくいきます。
ライアンR.ロサリオ

ライアン-コードを修正してくれませんか?old.var <-factor(1:2);の場合 あなたのコードは[1] "1" "2"(数値ではありません。)を与えるでしょう。
Eduardo Leoni

3
または少し効率的に:as.numeric(levels(old.var))[old.var]
ハドリー2009

6

この質問はしばらくの間出てきましたが、最近、コマンドを使用するためのSASおよびRブログですばらしいトリックを発見しましたcut。このコマンドは、データをカテゴリに分割するために使用されます。例として、irisデータセットを使用して、10個のカテゴリに分割します。

> 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

別のトリック。glmnetのような一部のパッケージは、設計行列と応答変数のみを入力として受け取ります。モデルを機能間のすべての相互作用に適合させたい場合、「y〜。^ 2」という式は使用できません。を使用expand.grid()すると、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

3
モデリング関数が式を受け入れない場合(これは非常にまれです!)model.matrix、?
ハドリー2009

良いですね。この機能の存在を知りませんでした。上記の関数はmodel.matrix(〜。^ 2 -1、X)と同等ですが、行列の受け渡しに関しては、glmnetを除いて、配列ポインターをカスタムC関数に渡すことがよくあります。実際、式を関数に渡す方法がわかりません。おもちゃの例はありますか?
ギャップの多い2009

5

私のお気に入りの1つは、やや正統でないトリックではないにしても、eval()およびの使用ですparse()。この例はおそらくそれがどのように役立つかを示しています

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

[1] "Albany"

このタイプの状況は少なからず発生し、使用eval()してparse()アドレスにそれを助けることができます。もちろん、これをコーディングする別の方法についてのフィードバックは歓迎します。


1
これは、名前の付いたベクトル要素でも実行できます。
Dirk Eddelbuettel、2009

3
library(fortunes); fortune(106)答えがparse()の場合、通常は質問を再考する必要があります。-Thomas Lumley R-help(2005年2月)
Eduardo Leoni

eval()とparse()が役立つ例を以下に示します。これには、バイオコンダクターパッケージ(hgu133a.dbなど)が含まれ、プローブセットIDに関するさまざまな情報を取得しようとします。例:ライブラリー(hgu133a.db)パラメーター<-'SYMBOL' mget( '202431_s_at'、env = eval(parse(text = paste( 'hgu133a'、parameter、sep = ''))))パラメーター<-'ENTREZID 'mget(' 202431_s_at '、env = eval(parse(text = paste(' hgu133a '、parameter、sep =' ')))
andrewj

Dirkが言うように、これは名前付きベクトル要素、または `get(paste(state、parameter、sep = '。'))`で行う方が良い
ハドリー

@ Hadley、get()をそのように使用できることを知りませんでした。ありがとう。
andrewj 2009

5

set.seed() 乱数ジェネレータの状態を設定します。

例えば:

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

ランダム関数を使用する例で非常に役立ちます...全員を同じページ
JD Long

5

Rから呼び出されるようにCを書いている人にとって.Internal(inspect(...))は便利です。例えば:

> .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コード/ライブラリ/'

ファイル= list.files(d、 '。r $')

for(f in files){if(!(f == 'mysource.r')){print(paste( 'Sourcing'、f))source(paste(d、f、sep = ''))}}

上記のコードを使用して、Rとの対話型セッションで使用するさまざまなユーティリティプログラムを使用して、起動時にディレクトリ内のすべてのファイルを調達します。より良い方法があると確信していますが、自分の仕事には便利です。これを行う行は次のとおりです。

source( "〜/ Rコード/ライブラリ/mysource.r")


6
しないでください。パッケージを作成します。
Dirk Eddelbuettel、2010年

ありがとう。私はroxygenで1つか2つのスレッドを見ていましたが、おそらく私は単純な自己使用パッケージを書いてみるべきレベルにいるようです。
mcheema 2010年

3

データフレーム内のいくつかの変数に対して操作を実行すること。これは、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)

1
最初はこれでかっこいいように見えますが、この種のコードは長い目で見ればトラブルの終わりにはなりません。常に明示的にすることをお勧めします。
ハドリー2009

ハム、私は最近このトリックをかなり使用しています。その際限のない問題について、具体的に教えてください。
イアンフェロー

多分ハドリーはplyrパッケージを代わりに使用することを提案していますか?
クリストファーデュボワ

3
いいえ、これはplyrを代わりに使用するというお勧めの提案ではありません。あなたのコードの基本的な問題は、それが意味的に怠惰であるということです-ユーザーに彼らが欲しいものを明示的に綴らせる代わりに、あなたは推測するためにいくつかの「魔法」を行います。これの問題は、関数をプログラムするのが非常に困難になることです。つまりget.vars、大量のフープを飛び越えずに呼び出す関数を書くのは困難です。
ハドリー2009

3

私はこれを一度投稿したことがありますが、それを使いすぎて、もう一度投稿するつもりでした。data.frameの名前と位置番号を返すためのほんの小さな関数です。確かに特別なことは何もありませんが、何度も使用せずにセッションを通過することはほとんどありません。

##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
これは本当に1行です:data.frame(VAR = names(df), COL = seq_along(df))
ハドリー2009

非常にエレガントで、おそらくni <-function(df){data.frame(VAR = names(df)、COL = seq_along(df))}に
切り替え

1
使用:data.frame(colnames(the.df))
Tal Galili
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.