R: применить функцию SVM для группировки по фрейму данных - PullRequest
1 голос
/ 09 февраля 2020

У меня есть фрейм данных (df), который выглядит следующим образом:

   Value Country ID
1   21   RU    AAAU9001025
2   24   NG    AAAU9001848
3   17   EG    ACLU2799370
4   2    EG    ACLU2799370
5   56   RU    ACLU2799370 

Я хочу запустить классификатор SVM для обнаружения выбросов по значению для каждой страны и на основе сравнительно небольшой выборки, я хочу чтобы указать, является ли это выброс в каждом ряду. Таким образом, мой вывод будет фреймом данных с дополнительным логическим столбцом, который указывает, является ли его выброс:

    Value Country ID    SVM
1   21  RU  AAAU9001025 FALSE
2   24  NG  AAAU9001848 FALSE
3   17  EG  ACLU2799370 FALSE
4   2   EG  ACLU2799370 TRUE
5   56  RU  ACLU2799370 TRUE
6   25  EG  AMFU3022141 FALSE

Я использую следующий код, но мне не удается создать нужный фрейм данных:

lapply(split(df,df$Country), 
       function(x) {(e1071::svm(x$Value[1:(ifelse(nrow(x)<50000,nrow(x),50000))], 
                                nu=0.98, type="one-classification", kernel="polynomial"))
         })

Пожалуйста, попробуйте помочь мне разобраться, спасибо!

1 Ответ

1 голос
/ 09 февраля 2020

имитируют что-то вроде ваших данных:

NROWS = c(3000,6000,10000)
names(NROWS)=c("RU","EG","NG")

df = lapply(names(NROWS),function(i){
data.frame(
Value = c(rnorm(0.9*NROWS[i]),rpois(0.1*NROWS[i],5)),
Country=i,
ID = paste0(i,"_",1:NROWS[i])
)
})

df = do.call(rbind,df)

Создайте функцию для выполнения SVM, потому что вы предсказываете на подмножестве, но возвращаете все ..

library(e1071)

SVM_f = function(x,limit=5000){
N = min(c(limit,length(x)))
mdl = svm(x[sample(length(x),N)],
nu=0.98, type="one-classification", kernel="polynomial")
predict(mdl,x)
}

res = by(df,df$Country,function(x){
data.frame(x,SVM = SVM_f(x$Value))
})
res = do.call(rbind,res)
          Value Country   ID   SVM
RU.1  1.2802954      RU RU_1 FALSE
RU.2 -2.7119588      RU RU_2 FALSE
RU.3 -0.4856534      RU RU_3 FALSE
RU.4 -0.5041824      RU RU_4 FALSE
RU.5 -0.7043723      RU RU_5 FALSE
RU.6  0.0472744      RU RU_6 FALSE

Вы также можете использовать dplyr , но он может работать немного медленнее:

library(dplyr)
df %>% group_by(Country) %>% mutate(SVM=SVM_f(Value))
...