2016-08-23 2 views
3

입력 벡터를 취하고 입력을 기반으로 데이터 프레임을 만들고 일부 값을 최적화 한 다음이 값 중 일부를 반환하는 코드를 만들었습니다. 지금은 이것을 입력 데이터 프레임에 대해 행 방향으로 적용하는 함수로 바꾸고 있습니다. 아래는 내가 달성하고자하는 것의 예를 작업 최소가 (내 실제 기능은 여기에 공유하는 데 시간이 너무 오래 될 것이다!) : 당신이 볼 수 있듯이, 나는 각각의 새로운 df$mean 개별 기능을 적용 할 수 없습니다사용자 정의 함수에서 데이터 프레임에 여러 열을 추가하는 방법 R

# Randomly generated dataframe 
df <- data.frame(a = rnorm(10, 0, 1), x = rnorm(10, 1, 3), y = rnorm(10, 2, 3)) 

# Function that takes multiple arguments and returns multiple values in a list 
zsummary <- function(x, y) { 
    if (y < 0) return(list(NA, NA)) 
    z = rnorm(10, x, abs(y)) 
    return(list(mean(z), sd(z))) 
} 

# Example of something that works using dplyr 
# However, this results in a lot of function calls... 
# especially if there were a lot of columns in the list... 
library(dplyr) 
df %>% rowwise() %>% 
    mutate(mean = zsummary(x,y)[[1]], sd = zsummary(x,y)[[1]]) 

dfsd 열은 z 벡터에만 의존하므로 한 번 생성 할 수 있습니다. 나는 이미 주위를 둘러 보았지만 아직 답을 찾을 수 없었다. 나는 해결책이 apply 함수 중 하나를 사용하고 dplyr에서 무언가를 사용하지 않을 것이라고 생각하지만 솔직히 완전히 이해했습니다. apply 함수. 나는 또한 이 아닌이 인 for 루프를 사용하는 솔루션을 좋아할 것입니다. 이전 프로젝트에서 이것을 시도한 적이 있으며 대용량 데이터 프레임의 경우 매우 느립니다!

답변

2

여기에 mapply을 사용할 수 있습니다. zsummary에는 두 개의 인수가 사용되므로 zsummary을 적용하려면 'x'및 'y'의 해당 요소를 사용하므로 mapply이 하나의 옵션이됩니다.

t(mapply(zsummary, df$x, df$y)) 

우리는 또한 약간의 기능을 변경하고 dplyr

zsummary <- function(x, y) { 
    if (y < 0) return(data.frame(mean = NA, sd = NA)) 
    z = rnorm(10, x, abs(y)) 
    data.frame(mean = mean(z), sd = sd(z)) 
} 

df %>% 
    rowwise() %>% 
    do(data.frame(., zsummary(.$x, .$y))) 

과 출력을 얻을 또는 수 있습니다 우리가 대신 여러 인자를 고려하여 기능을 갖는의, 코멘트에서 논의 된 바와 같이, 단일 인수가 있고 각 행에 적용 할 경우 과 MARGIN=1을 사용하십시오.

zsummary2 <- function(v1){ 
     if(v1[2] < 0) return(c(mean = NA, sd = NA)) 
     z <- rnorm(10, v1[1], abs(v1[2])) 
     c(mean = mean(v1), sd= sd(v1)) 
    } 

t(apply(df[-1], 1, zsummary2)) 
#   mean  sd 
# [1,] 1.403066 0.8757504 
# [2,] 5.058188 5.1401507 
# [3,] 4.288365 1.4194393 
# [4,] 1.932829 6.7587054 
# [5,] -1.864236 3.7587462 
# [6,]  NA  NA 
# [7,] 3.328629 1.3711950 
# [8,] -2.347699 5.0449958 
# [9,] 2.936615 1.7332283 
#[10,]  NA  NA 

참고 : 우리는 rnorm에 대한 씨앗을 설정하지 않은 것처럼 값은 각 실행에서 다릅니다.

+0

답장을 보내 주셔서 감사합니다. x와 y를 다룰 수있는 다른 방법이 있습니까? 내 실제 입력에는 12 개 정도의 열이 있으므로 colnames와 같은 것을 사용하면 mapply에서 내 함수를 사용하려고 할 때마다 입력 $ a, 입력 $ b, 입력 $ c를 저장하는 데 아주 좋을 것입니다. – Alwin

+1

@ Alwin 데이터 집합의 열과 같은 단일 인수를 취하여 내부에서 처리하는 방식으로 함수를 만들 수 있습니다. 더 좋을 수도 있습니다. – akrun

+0

+1 또한 대답을 upvote하기에 충분한 담당자가 없으므로. 아무 것도 없으면 정답으로 받아 들일 것입니다. – Alwin

관련 문제