UFO ET IT

당신이 만난 가장 큰 R-gotcha는 무엇입니까?

ufoet 2020. 12. 13. 10:00
반응형

당신이 만난 가장 큰 R-gotcha는 무엇입니까?


언젠가 정말 놀랐던 어떤 알갓 차가 있나요? 나는 우리 모두가 이것을 공유함으로써 얻을 것이라고 생각합니다.

다음은 내 꺼야 : 목록 색인으로 my.list[[1]]하지 않습니다 my.list[1]. R의 초기에 이것을 배웠습니다.


데이터 프레임에서 행을 제거하면 고유하지 않은 이름의 행이 추가되고 오류가 발생합니다.

> 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. 세 번째 행이 삭제되므로 행 이름은 c (1,2,4)입니다.

  3. 네 번째 행이 추가되고 R은 자동으로 인덱스 즉 4와 동일한 행 이름을 설정하므로 행 이름은 c (1,2,4,4)입니다. 행 이름은 고유해야하므로 이는 불법입니다. R에서 이러한 유형의 동작을 허용해야하는 이유를 모르겠습니다. R이 고유 한 행 이름을 제공해야하는 것 같습니다.


[Hadley는 의견에서 이것을 지적했습니다 .]

시퀀스를 반복을위한 인덱스로 사용할 때 seq_along().NET과 같은 것보다 함수 를 사용하는 것이 좋습니다 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)
>

데이터를로드 할 때 요소 자동 생성. 무심코 데이터 프레임의 열을 문자로 취급하고, 이는 값을 수준이 아닌 값으로 변경하려고 할 때까지 잘 작동합니다. 이것은 경고를 생성하지만 데이터 프레임에 NA가있는 상태로 남습니다.

R 스크립트에서 예기치 않게 문제가 발생하면 요인이 원인이 아닌지 확인하십시오.


행렬을 단일 차원으로 부분 집합화할 때 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> 

먼저 이진법에서 숫자를 표현하는 근본적인 문제를 이해하고 있다고 말씀 드리겠습니다. 그럼에도 불구하고 쉽게 개선 될 수 있다고 생각하는 한 가지 문제는 십진수 값이 R의 일반적인 표현 범위를 벗어 났을 때 숫자를 표현하는 것입니다.

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

결과가 실제로 정수로 표현 될 수있을 때 결과가 정수로 표현 되어도 상관 없습니다. 예를 들어 값이 실제로 1020이면 x에 대해 인쇄하는 것이 좋습니다. 그러나이 경우 x를 인쇄 할 때 1020.0만큼 간단한 것이 값이 정수가 아니고 1로 표현할 수 없음을 더 분명하게 만들었습니다. R은 표시되지 않는 극히 작은 소수 구성 요소가있을 때 일종의 표시로 기본 설정되어야합니다.


NA, NaN및의 조합을 허용해야하는 것은 성 가실 수 있습니다 Inf. 그들은 다르게 행동하며, 하나에 대한 테스트가 다른 사람들에게 반드시 작동하는 것은 아닙니다.

> 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

항상 NA!

(많은 고통스러운 경험 이후) 항상주의를 기울여야하는 한 가지는 NA가치입니다. R 함수는 사용하기 쉽지만 어떤 프로그래밍 방식으로도 데이터 문제를 극복 할 수 없습니다.

예를 들어를 사용하는 모든 순 벡터 연산 NANA입니다. 이것은 얼굴에 "놀라운"것입니다.

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

이것은 다른 상위 수준 함수로 외삽됩니다.

즉, 결 측값은 기본적으로 측정 값만큼 중요합니다 . 많은 기능에는 na.rm=TRUE/FALSE기본값이 있습니다. 이러한 기본 설정을 해석하는 방법을 결정하는 데 시간을 할애 할 가치가 있습니다.

편집 1 : Marek이 훌륭한 지적을합니다. 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에 대한 모든 좋은 동작입니다. 그러나 처음에는 심각한 두통을 유발할 수 있습니다.


그것을 잊고 strptime()친구들 은 항상 9 인 POSIXt POSIXltlength()으로 돌아온다 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> 

round함수는 항상 짝수로 반올림됩니다.

> round(3.5)
[1] 4  

> round(4.5)
[1] 4

정수에 대한 수학은 복식과 미묘하게 다릅니다 (때로는 복잡함도 이상합니다)

업데이트 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

아무도 이것을 언급하지 않는다는 것에 놀랐습니다.

TF대체 될 수 있습니다 TRUEFALSE하지 않습니다.

예:

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나를 속일. Shane은 그의 코멘트에서 이것에 대해 언급했습니다 .


데이터를 읽는 것은 생각보다 더 문제가 될 수 있습니다. 오늘 나는 read.csv () 를 사용 하면 .csv 파일의 한 줄이 비어 있으면 read.csv ()가 자동으로 건너 뛰는 것을 발견했습니다. 이것은 대부분의 응용 프로그램에서 의미가 있지만 수천 개의 파일에서 27 행에서 데이터를 자동으로 추출하고 이전 행 중 일부가 비어 있거나 비어 있지 않을 수 있습니다.주의하지 않으면 상황이 끔찍하게 진행될 수 있습니다. 잘못된.

나는 지금 사용한다

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

데이터를 가져올 때 실제로하고 있다고 생각하는 작업을 계속 반복하고 있는지 확인하십시오.


all.equal()함수 의 까다로운 동작 .

내 연속 오류 중 하나는 부동 소수점 숫자 집합을 비교하는 것입니다. 다음과 같은 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()설명 을 몇 번이나 읽었는지 ...


이것은 너무 아파서 버그 보고서에 주석을 추가하는 데 몇 시간을 보냈습니다 . 내 소원을 얻지 못했지만 최소한 다음 버전의 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

  1. 빈 괄호를 포함하는 것을 잊어 버려 실수로 함수의 소스 코드를 나열합니다. 예 : "ls"대 "ls ()"

  2. true & false는 Matlab, C ++, Java, Python과 같이 미리 정의 된 상수로 자르지 않습니다. TRUE 및 FALSE를 사용해야합니다.

  3. 보이지 않는 반환 값 : 예를 들어 ".packages ()"는 아무것도 반환하지 않는 반면 "(.packages ())"는 패키지 기본 이름의 문자형 벡터를 반환합니다.


예를 들어 숫자 3.14는 숫자 상수이지만 +3.14 및 -3.14 표현식은 함수 +-다음을 호출합니다 .

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

John Chambers 책 Software for Data Analysis -Programming with R의 섹션 13.2 참조


길이가 0 인 벡터에는 몇 가지 단점이 있습니다.

R> kk=vector(mode="numeric",length=0)
R> kk
numeric(0)
R> sum(kk)
[1] 0
R> var(kk)
[1] NA

$연산자의 부분 일치 : 이것은 목록에 적용되지만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"]]

[[운영자는 또한이 exact플래그를하지만 다행히도이다 TRUE기본적으로.

부분 일치는 다음에도 영향을줍니다 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)

목록으로 작업 할 때 직관적이지 않은 몇 가지 사항이 있습니다.

물론, 차이 [와는 [[익숙해 지는데 좀 걸립니다. 리스트를 들어, [(가), 반면 (잠재적 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)

R에서 가장 큰 혼란 중 하나는 [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에서 요소 수준을 삭제하지 않습니다.


인덱스로 사용되는 벡터의 자동 반복 ( "재활용" ) :

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?

컴파일 된 언어와 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

If you try to do the same thing in R, you have to put the nested function first, or you get an error! Just because you've defined the function, it's not in the namespace until it's assigned to a variable! On the other hand, the function can refer to a variable that has not been defined yet.

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

  v1 <- 1

  v2 = f2()

  print(sprintf("2 == %d", v2))
}

Mine from today: qnorm() takes Probabilities and pnorm() takes Quantiles.


For me it is the counter intuitive way in which when you export a data.frame to a text file using write.csv, then to import it afterwards you need to add an additional argument to get exactly the same data.frame, like this:

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

I also posted this question in SO and was suggested as an answer to this Q by @BenBolker.


The apply set of functions does not only work for matrices, but scales up to multi-dimensional array's. In my research I often have a dataset of for example temperature of the atmosphere. This is stored in a multi-dimensional array with dimensions x,y,level,time, from now on called multi_dim_array. A mockup example would be:

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

Using apply one can easily get the:

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

This makes the margin argument to apply seem much less counter intuitive. I first though, why not use "row" and "col" instead of 1 and 2. But the fact that it also works for array's with more dimensions makes it clear why using margin like this is preferred.

참고URL : https://stackoverflow.com/questions/1535021/whats-the-biggest-r-gotcha-youve-run-across

반응형