2012-04-06 4 views
2

apply를 사용하여 함수에 데이터 프레임의 행을 전달하면 해당 행의 요소 클래스 정보가 손실됩니다. 그들은 모두 '인물'로 변합니다. 다음은 간단한 예입니다. 나는 3 세의 나이들에게 2 년을 더하고 싶다. 내가 숫자 2였던 값을 추가하려고 할 때 R은 "이진 연산자에 숫자가 아닌 인수"라고 말합니다. 어떻게 이것을 피할 수 있습니까?R을 적용 할 때 클래스 정보를 잃을 때

age = c(20, 30, 50) 
who = c("Larry", "Curly", "Mo") 
df = data.frame(who, age) 
colnames(df) <- c('_who_', '_age_') 
dfunc <- function (er) { 

    print(er['_age_']) 
    print(er[2]) 
    print(is.numeric(er[2])) 

    print(class(er[2])) 
    return (er[2] + 2) 
} 
a <- apply(df,1, dfunc) 

출력은 다음과 같습니다

_age_ 
"20" 
_age_ 
"20" 
[1] FALSE 
[1] "character" 
Error in er[2] + 2 : non-numeric argument to binary operator 

답변

7

apply은 정말 (모든 요소에 대해 동일한 유형이) 행렬에서 작동합니다. data.frame에서 실행하면 as.matrix이 먼저 호출됩니다.

이 주변에 가장 쉬운 방법은 숫자 열에서 작동하는 것입니다

# skips the first column 
a <- apply(df[, -1, drop=FALSE],1, dfunc) 

# Or in two steps: 
m <- as.matrix(df[, -1, drop=FALSE]) 
a <- apply(m,1, dfunc) 

drop=FALSE가 하나의 열 벡터를 입지 않도록 필요합니다. -1는 모든하지만-첫 번째 열, 대신 명시 적으로 예를 들어, 당신이 원하는 열을 지정할 수 있음을 의미 df[, c('foo', 'bar')]

UPDATE

당신이 당신의 함수는 하나 개 전체 data.frame 행을 액세스하려면

# "loop" over the index and extract a row at a time 
sapply(seq_len(nrow(df)), function(i) dfunc(df[i,])) 

# Use split to produce a list where each element is a row 
sapply(split(df, seq_len(nrow(df))), dfunc) 

첫 번째 옵션은이 선행 거대한 목록 구조를 만들 필요가 없기 때문에 대용량 데이터 프레임 아마 더 : 시간, 두 가지 옵션 (적어도)가있다.

+0

내 응용 프로그램에서 내 데이터 프레임이 크고 행의 항목 중 하나를 업데이트하는 데 사용되는 datetimes 및 다른 열이 있습니다. 나는 값을 datetimes로 변환하는 오버 헤드와 함수가 호출 될 때마다 double을 피하기를 희망했다. – Jack

+0

@ 잭 - 오케이, 대안으로 업데이트했습니다. – Tommy

+0

관련 컨텍스트에서 유용하다는 것을 알았습니다 : df [sapply (df, is.numeric)] – PatrickT

관련 문제