58

ある日本当に驚いたR-落とし穴はありますか? これらを共有することで、私たち全員が利益を得られると思います。

ここに私のものがあります: リストの索引付けでは、my.list[[1]]is notmy.list[1]です。R の初期の頃にこれを学びました。

4

29 に答える 29

43

[Hadleyはコメントでこれを指摘しました。]

反復のインデックスとしてシーケンスを使用する場合は、 のseq_along()ようなものではなく関数を使用することをお勧めします1:length(x)

ここでベクトルを作成すると、どちらのアプローチも同じものを返します。

> x <- 1:10
> 1:length(x)
 [1]  1  2  3  4  5  6  7  8  9 10
> seq_along(x)
 [1]  1  2  3  4  5  6  7  8  9 10

ベクトルを作成しますNULL

> x <- NULL
> seq_along(x) # returns an empty integer; good behavior
integer(0)
> 1:length(x) # wraps around and returns a sequence; this is bad
[1] 1 0

これにより、ループ内で混乱が生じる可能性があります。

> for(i in 1:length(x)) print(i)
[1] 1
[1] 0
> for(i in seq_along(x)) print(i)
>
于 2010-06-23T14:22:45.277 に答える
36

データをロードするときの因子の自動作成。データフレーム内の列を無意識のうちに文字として扱います。これは、値をレベルではない値に変更しようとするようなことをするまではうまく機能します。これにより警告が生成されますが、データフレームにはNAが含まれたままになります...

Rスクリプトで予期しない問題が発生した場合は、要因が原因ではないことを確認してください。

于 2009-10-08T02:54:13.723 に答える
32

データフレーム内の行を削除すると、一意でない名前の行が追加され、エラーが発生します。

> a<-data.frame(c(1,2,3,4),c(4,3,2,1))
> a<-a[-3,]
> a
  c.1..2..3..4. c.4..3..2..1.
1             1             4
2             2             3
4             4             1
> a[4,1]<-1
> a
Error in data.frame(c.1..2..3..4. = c("1", "2", "4", "1"), c.4..3..2..1. = c(" 4",  : 
  duplicate row.names: 4

したがって、ここで何が起こっているかは次のとおりです。

  1. 4 行の data.frame が作成されるため、行名は c(1,2,3,4) になります。

  2. 3 番目の行が削除されるため、行名は c(1,2,4) になります。

  3. 4 番目の行が追加され、R は行名をインデックス、つまり 4 に自動的に設定するため、行名は c(1,2,4,4) になります。行名は一意でなければならないため、これは不正です。このタイプの動作が R で許可される理由がわかりません。R は一意の行名を提供する必要があるように思えます。

于 2009-10-08T03:15:45.603 に答える
32

行列を 1 次元にサブセット化する際に drop=FALSE 引数を忘れたため、オブジェクト クラスも削除されます。

R> X <- matrix(1:4,2)
R> X
     [,1] [,2]
[1,]    1    3
[2,]    2    4
R> class(X)
[1] "matrix"
R> X[,1]
[1] 1 2
R> class(X[,1])
[1] "integer"
R> X[,1, drop=FALSE]
     [,1]
[1,]    1
[2,]    2
R> class(X[,1, drop=FALSE])
[1] "matrix"
R> 
于 2009-10-08T02:02:03.663 に答える
25

まず、バイナリ システムで数値を表す基本的な問題を理解していると言わせてください。それにもかかわらず、私が簡単に改善できると思う 1 つの問題は、10 進数値が R の典型的な表示範囲を超えている場合の数値の表示です。

x <- 10.2 * 100
x
1020
as.integer(x)
1019

実際に整数として表現できる場合、結果が整数として表現されてもかまいません。たとえば、値が実際に 1020 だった場合、x にそれを出力しても問題ありません。しかし、この場合、 x を出力するときに 1020.0 のような単純なものを使用すると、値が整数ではなく、1 として表現できないことがより明確になります。R は、表示されない非常に小さな小数部分がある場合に、何らかの表示をデフォルトにする必要があります。

于 2010-08-03T17:04:22.110 に答える
20

NA、、NaNおよびの組み合わせを考慮しなければならないのは面倒な場合がありInfます。それらは異なる動作をし、1つのテストが他のテストで必ずしも機能するとは限りません。

> x <- c(NA,NaN,Inf)
> is.na(x)
[1]  TRUE  TRUE FALSE
> is.nan(x)
[1] FALSE  TRUE FALSE
> is.infinite(x)
[1] FALSE FALSE  TRUE

ただし、これらのトラブルメーカーのいずれかをテストする最も安全な方法は次のとおりです。

> is.finite(x)
[1] FALSE FALSE FALSE
于 2010-08-14T13:36:14.303 に答える
18

NA! があるときに何が起こるかを常にテストします。

(多くのつらい経験を経て)私が常に注意を払う必要があることの 1 つは、NA価値観です。R 関数は使いやすいですが、データに関する問題をプログラミングで解決する方法はありません。

たとえば、 を使用した正味のベクトル演算NAは と等しくなりNAます。これは一見「驚くべき」ことです。

> x <- c(1,1,2,NA)
> 1 + NA
[1] NA
> sum(x)
[1] NA
> mean(x)
[1] NA

これは、他の高レベル関数に外挿されます。

つまり、欠損値は、多くの場合、デフォルトで測定値と同じくらい重要です。多くの関数にはna.rm=TRUE/FALSEデフォルトがあります。これらのデフォルト設定をどのように解釈するかを決めるのに時間を費やす価値があります。

編集1:マレクは素晴らしい点を挙げています. NA値は、インデックスで紛らわしい動作を引き起こす可能性もあります。例えば:

> TRUE && NA
[1] NA
> FALSE && NA
[1] FALSE
> TRUE || NA
[1] TRUE
> FALSE || NA
[1] NA

これは、(if ステートメントの) 条件式を作成しようとしている場合にも当てはまります。

> any(c(TRUE, NA))
[1] TRUE
> any(c(FALSE, NA))
[1] NA
> all(c(TRUE, NA))
[1] NA

これらの NA 値が最終的にベクトル インデックスになると、多くの予期しないことが続く可能性があります。これは、欠損値に注意する必要があることを意味するため、R ではすべて適切な動作です。しかし、最初は大きな頭痛を引き起こす可能性があります。

于 2009-10-08T03:36:29.823 に答える
13

関数はround常に偶数に丸められます。

> round(3.5)
[1] 4  

> round(4.5)
[1] 4
于 2011-05-26T16:58:07.507 に答える
13

それを忘れるとstrptime()、友達はいつも 9 のPOSIXt POSIXlt場所に戻ってきます。length()変換すると次のようになりPOSIXctます。

R> length(strptime("2009-10-07 20:21:22", "%Y-%m-%d %H:%M:%S"))
[1] 9
R> length(as.POSIXct(strptime("2009-10-07 20:21:22", "%Y-%m-%d %H:%M:%S")))
[1] 1
R> 
于 2009-10-08T02:27:03.800 に答える
12

整数の数学は double とは微妙に異なります (また、複素数も奇妙である場合があります)。

UPDATE彼らはR 2.15でいくつかのことを修正しました

1^NA      # 1
1L^NA     # NA
(1+0i)^NA # NA 

0L %/% 0L # 0L  (NA from R 2.15)
0 %/% 0   # NaN
4L %/% 0L # 0L  (NA from R 2.15)
4 %/% 0   # Inf
于 2011-08-10T19:03:14.720 に答える
11

誰もこれについて言及していないことに驚いていますが、

T&Fは上書きできますが、TRUE&FALSEはできません。

例:

x <- sample(c(0,1,NA), 100, T)
T <- 0:10

mean(x, na.rm=T)
# Warning in if (na.rm) x <- x[!is.na(x)] :
#   the condition has length > 1 and only the first element will be used
# Calls: mean -> mean.default
# [1] NA

plot(rnorm(7), axes=T)
# Warning in if (axes) { :
#   the condition has length > 1 and only the first element will be used
# Calls: plot -> plot.default
# Warning in if (frame.plot) localBox(...) :
#   the condition has length > 1 and only the first element will be used
# Calls: plot -> plot.default

[編集]ctrf+F私をだまします。シェーンは彼のコメントでこれについて言及しています。

于 2011-05-27T09:30:44.227 に答える
8

データの読み取りは、あなたが思っているよりも問題になる可能性があります。今日、 read.csv()を使用すると、.csv ファイルの行が空白の場合、read.csv()が自動的にスキップすることがわかりました。これはほとんどのアプリケーションにとって理にかなっていますが、(たとえば) 数千のファイルから 27 行目からデータを自動的に抽出する場合、その前の行の一部が空白である場合とそうでない場合があります。違う。

今使ってる

data1 <- read.table(file_name, blank.lines.skip = F, sep = ",")

データをインポートするときは、実際に行っていると思っていることを何度も何度も行っていることを確認してください...

于 2011-11-02T10:49:08.047 に答える
8

関数のトリッキーな動作all.equal()

私の継続的なエラーの 1 つは、一連の浮動小数点数を比較することです。次のような CSV があります。

... mu,  tau, ...
... 0.5, 1.7, ...

ファイルを読み取ってデータをサブセット化しようとすると、うまくいくこともあれば失敗することもあります - もちろん、浮動小数点トラップの穴に何度も何度も陥るからです。最初は、データには整数値のみが含まれていましたが、後で常に実数に変換されます。これはご存知のとおりです。比較は演算子でall.equal()はなく関数で行う必要があります==が、もちろん、最初に書いたコードは後者のアプローチを使用していました。

ええ、クールですが、同じ数をall.equal()返しますTRUEが、失敗した場合はテキストのエラー メッセージが表示されます。

> all.equal(1,1)
[1] TRUE
> all.equal(1:10, 1:5)
[1] "Numeric: lengths (10, 5) differ"
> all.equal(1:10, c(1:5,1:5))
[1] "Mean relative difference: 0.625"

解決策は関数を使用していisTRUE()ます:

if (!isTRUE(all.equal(x, y, tolerance=doubleErrorRate))) {
    ...
}

何度all.equals()説明を読んだことか…

于 2012-02-10T09:54:24.020 に答える
7

これは非常に痛かったので、バグレポートにコメントを追加するのに何時間も費やしました。望みは叶いませんでしたが、少なくとも次のバージョンの R ではエラーが発生するでしょう。

R> nchar(factor(letters))
 [1] 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

更新: R 3.2.0 以降 (おそらくそれ以前)、この例ではエラー メッセージが生成されるようになりました。以下のコメントで述べたように、因子はベクトルではなく、nchar() にはベクトルが必要です。

R> nchar(factor(letters))
Error in nchar(factor(letters)) : 'nchar()' requires a character vector
R> is.vector(factor(letters))
[1] FALSE
于 2012-02-21T18:45:54.043 に答える
6
  1. 空の括弧を含めるのを忘れて、誤って関数のソース コードをリストする: 例: "ls" 対 "ls()"

  2. true と false は、Matlab、C++、Java、Python のように、事前定義された定数としてカットしません。TRUE と FALSE を使用する必要があります

  3. 非表示の戻り値: たとえば、".packages()" は何も返しませんが、"(.packages())" はパッケージ ベース名の文字ベクトルを返します。

于 2009-10-08T01:54:05.777 に答える
5

たとえば、数値3.14は数値定数ですが、式+3.14および-3.14は関数+および-:の呼び出しです。

> class(quote(3.14))
[1] "numeric"
> class(quote(+3.14))
[1] "call"
> class(quote(-3.14))
[1] "call"

JohnChambersの著書「SoftwareforDataAnalysis -ProgrammingwithR 」のセクション13.2を参照してください。

于 2009-11-06T12:04:18.290 に答える
5

Partial matching in the $ operator: This applies to lists, but also on data.frame

df1 <- data.frame(foo=1:10, foobar=10:1)
df2 <- data.frame(foobar=10:1)

df1$foo # Correctly gets the foo column
df2$foo # Expect NULL, but this returns the foobar column!!!

# So, should use double bracket instead:
df1[["foo"]]
df2[["foo"]]

The [[ operator also has an exact flag, but it is thankfully TRUE by default.

Partial matching also affects attr:

x1 <- structure(1, foo=1:10, foobar=10:1)
x2 <- structure(2, foobar=10:1)

attr(x1, "foo") # Correctly gets the foo attribute
attr(x2, "foo") # Expect NULL, but this returns the foobar attribute!!!

# So, should use exact=TRUE
attr(x1, "foo", exact=TRUE)
attr(x2, "foo", exact=TRUE)
于 2011-08-10T18:52:38.767 に答える
5

長さゼロのベクトルにはいくつかの癖があります。

R> kk=vector(mode="numeric",length=0)
R> kk
numeric(0)
R> sum(kk)
[1] 0
R> var(kk)
[1] NA
于 2012-02-20T16:53:08.793 に答える
5

インデックスとして使用されるベクトルの自動繰り返し ( "recycling" ):

R> all.numbers <- c(1:5)
R> all.numbers
[1] 1 2 3 4 5
R> good.idxs <- c(T,F,T)
R> #note unfortunate length mismatch
R> good.numbers <- all.numbers[good.idxs]
R> good.numbers
[1] 1 3 4
R> #wtf? 
R> #why would you repeat the vector used as an index 
R> #without even a warning?
于 2011-12-30T23:04:18.337 に答える
4

リストを操作すると、直感的でないことがいくつかあります。

もちろん、 と の違いには[慣れ[[が必要です。リストの場合、 は[(場合によっては 1 つの) 要素のリストを返しますが、[[はリスト内の要素を返します。

リストの作成:

# When you're used to this:
x <- numeric(5) # A vector of length 5 with zeroes
# ... this might surprise you
x <- list(5)    # A list with a SINGLE element: the value 5
# This is what you have to do instead:
x <- vector('list', 5) # A vector of length 5 with NULLS

では、NULL をリストに挿入する方法は?

x <- list("foo", 1:3, letters, LETTERS) # A sample list
x[[2]] <- 1:5        # Put 1:5 in the second element
# The obvious way doesn't work: 
x[[2]] <- NULL       # This DELETES the second element!
# This doesn't work either: 
x[2] <- NULL       # This DELETES the second element!

# The solution is NOT very intuitive:
x[2] <- list(NULL) # Put NULL in the second element

# Btw, now that we think we know how to delete an element:
x <- 1:10
x[[2]] <- NULL  # Nope, gives an ERROR!
x <- x[-2]    # This is the only way for atomic vectors (works for lists too)

最後に、ネストされたリストを介したインデックス作成などの高度なもの:

x <- list(a=1:3, b=list(c=42, d=13, e="HELLO"), f='bar')
x[[c(2,3)]] # HELLO (first selects second element and then it's third element)
x[c(2,3)]   # The second and third elements (b and f)
于 2011-08-11T16:27:11.333 に答える
4

R での大きな混乱の 1 つは、[i, drop = TRUE]因子レベルを下げることですが、そうで[i, j, drop = TRUE]はありません!

> df = data.frame(a = c("europe", "asia", "oceania"), b = c(1, 2, 3))
> df$a[1:2, drop = TRUE]
[1] europe asia  
Levels: asia europe          <---- drops factor levels, works fine
> df[1:2,, drop = TRUE]$a
[1] europe asia  
Levels: asia europe oceania  <---- does not drops factor levels!

詳細については、以下を参照してください: drop = TRUE は、ベクトルではドロップしますが、data.frame ではファクター レベルをドロップしません。

于 2013-01-02T15:41:17.860 に答える
3

私にとっては、を使用してdata.frameをテキストファイルにエクスポートし、後でwrite.csvそれをインポートするときに、次のようにまったく同じdata.frameを取得するために引数を追加する必要があるという直感に反する方法です。

write.csv(m, file = 'm.csv')
read.csv('m.csv', row.names = 1) # Note the row.names argument

私もこの質問をSOに投稿し、@BenBolkerによってこのQへの回答として提案されました。

于 2012-09-20T13:03:56.057 に答える
3

コンパイルされた言語と Matlab から来て、関数型言語の関数の基本的な側面について時々混乱することがあります。関数は使用する前に定義する必要があります。R インタープリターによって解析されるだけでは十分ではありません。ネストされた関数を使用する場合、これはほとんど頭をもたげます。

Matlab では、次のことができます。

function f1()
  v1 = 1;
  v2 = f2();
  fprintf('2 == %d\n', v2);

  function r1 = f2()
    r1 = v1 + 1 % nested function scope
  end
end

R で同じことをしようとすると、ネストされた関数を最初に配置する必要があります。そうしないと、エラーが発生します。関数を定義したからといって、変数に割り当てられるまで名前空間にはありません! 一方、関数はまだ定義されていない変数を参照できます。

f1 <- function() {
  f2 <- function() {
    v1 + 1
  }

  v1 <- 1

  v2 = f2()

  print(sprintf("2 == %d", v2))
}
于 2009-10-18T14:09:28.960 に答える
3

今日の私のもの: qnorm() は確率を取り、pnorm() は分位数を取ります。

于 2010-08-03T15:50:56.987 に答える
1

関数のapplyセットは、行列に対して機能するだけでなく、多次元配列までスケールアップします。私の研究では、大気の温度などのデータセットをよく持っています。これは、次元 の多次元配列に格納され、今後はx,y,level,timeと呼ばれmulti_dim_arrayます。モックアップの例は次のとおりです。

multi_dim_array = array(runif(96 * 48 * 6 * 100, -50, 50), 
                        dim = c(96, 48, 6, 100))
> str(multi_dim_array)
#     x     y     lev  time    
 num [1:96, 1:48, 1:6, 1:100] 42.4 16 32.3 49.5 24.9 ...

1つを使用applyすると、次のものが簡単に取得できます。

# temporal mean value
> str(apply(multi_dim_array, 4, mean))
 num [1:100] -0.0113 -0.0329 -0.3424 -0.3595 -0.0801 ...
# temporal mean value per gridcell (x,y location)
> str(apply(multi_dim_array, c(1,2), mean))
 num [1:96, 1:48] -1.506 0.4553 -1.7951 0.0703 0.2915 ...
# temporal mean value per gridcell and level (x,y location, level)
> str(apply(multi_dim_array, c(1,2,3), mean))
 num [1:96, 1:48, 1:6] -3.839 -3.672 0.131 -1.024 -2.143 ...
# Spatial mean per level
> str(apply(multi_dim_array, c(3,4), mean))
 num [1:6, 1:100] -0.4436 -0.3026 -0.3158 0.0902 0.2438 ...

これにより、margin議論applyは直感に反するものではなくなります。最初に、1 と 2 の代わりに "row" と "col" を使用してみませんか。しかし、より多くの次元を持つ配列でも機能するという事実は、marginこのような使用が好まれる理由を明確にします。

于 2012-11-06T08:07:49.337 に答える