2017-02-16 4 views
1

Как я могу «применить» определенную пользователем функцию к каждой строке фрейма данных, если пользовательская функция принимает функцию в качестве аргумента?Применить пользовательскую функцию, которая принимает функцию как аргумент

Вот пример ... Предположим, у меня есть три столбца в кадре данных, каждый из которых содержит целые числа. Для каждой строки я хотел бы взять минимальное целое число и преобразовать его в соответствующую букву с помощью набора данных поиска. Аналогичным образом выполните одну задачу с максимальным целым числом. Результат будет таким:

 
Col1 | Col2 | Col3 | MaxVal | MinVal | 
------------------------------------- 
1  2  1  B  A 
4  4  1  F  A 
5  6  2  F  B 

ниже код причины: Error in $<-.data.frame(*tmp*, "MaxVal", value = integer(0)) : replacement has 0 rows, data has 3

myData <- data.frame("Col1" = c(1, 4, 5), "Col2" = c(2, 6, 6), "Col3" = c(1, 1, 2)) 
numberToLetterData <- data.frame("Number" = 1:6, "Letter" = c("A", "B","C","D","E","F")) 

GetMinOrMaxForRow <- function(x, refData, functionToUse){ 
    refData$Letter[refData$Number == functionToUse(x)] 
} 

myData$MinVal <- apply(myData, 1, FUN = function(x) GetMinOrMaxForRow(x = x, refData = numberToLetterData, functionToUse = min)) 
myData$MaxVal <- apply(myData, 1, FUN = function(x) GetMinOrMaxForRow(x = x, refData = numberToLetterData, functionToUse = max)) 

... но следующий код (с последними двумя линиями переключился) работает отлично:

myData <- data.frame("Col1" = c(1, 4, 5), "Col2" = c(2, 6, 6), "Col3" = c(1, 1, 2)) 
numberToLetterData <- data.frame("Number" = 1:6, "Letter" = c("A", "B","C","D","E","F")) 

GetMinOrMaxForRow <- function(x, refData, functionToUse){ 
    refData$Letter[refData$Number == functionToUse(x)] 
} 

myData$MaxVal <- apply(myData, 1, FUN = function(x) GetMinOrMaxForRow(x = x, refData = numberToLetterData, functionToUse = max)) 
myData$MinVal <- apply(myData, 1, FUN = function(x) GetMinOrMaxForRow(x = x, refData = numberToLetterData, functionToUse = min)) 

... Кто-нибудь знает, почему?

+0

Af тер, вызывающий первую строку, вы назначаете myData $ MinVal. В следующей строке вы создадите максимум по всей строке в вашем фреймворке данных, включая новый столбец MinVal. – c0bra

ответ

0

После вызова первой строки вы назначаете myData $ MinVal. В следующей строке вы создадите максимум по всей строке в вашем фреймворке данных, включая новый столбец MinVal.

Поэтому не применяйте функцию ко всем столбцам, то есть myData [, 1: 3].

myData <- data.frame("Col1" = c(1, 4, 5), "Col2" = c(2, 6, 6), "Col3" = c(1, 1, 2)) 
numberToLetterData <- data.frame("Number" = 1:6, "Letter" = c("A", "B","C","D","E","F")) 

GetMinOrMaxForRow <- function(x, refData, functionToUse){ 
    refData$Letter[refData$Number == functionToUse(x)] 
} 

myData$MinVal <- apply(myData[,1:3], 1, FUN = function(x) GetMinOrMaxForRow(x = x, refData = numberToLetterData, functionToUse = min)) 
myData$MaxVal <- apply(myData[,1:3], 1, FUN = function(x) GetMinOrMaxForRow(x = x, refData = numberToLetterData, functionToUse = max)) 
0

Использование dplyr вы можете сделать:

myData %>% 
    rowwise %>% 
    mutate(minVal = lookup[min(Col1, Col2, Col3)], 
     maxVal = lookup[max(Col1, Col2, Col3)]) 

Или в 2 шага, поэтому первое вычисление функции, а затем делает поиск:

myData %>% 
    rowwise %>% 
    mutate(minVal = min(Col1, Col2, Col3), 
     maxVal = max(Col1, Col2, Col3)) %>% 
    mutate_at(vars(minVal, maxVal), function(x) lookup[x]) 

Использование purrr вы можете сделать:

require(purrr) 
lookup <- setNames(LETTERS[1:6], 1:6) 
myData %>% 
    by_row(~lookup[min(.[1:3])], .collate = "cols", .to = "minVal") %>% 
    by_row(~lookup[max(.[1:3])], .collate = "cols", .to = "maxVal") 
Смежные вопросы