R выбрать 80% от каждого пользователя для обучения - PullRequest
0 голосов
/ 02 июля 2018

Набор данных представляет предпочтения пользователя в группе фильмов. Цель состоит в том, чтобы получить 80% рейтинга каждого пользователя для обучения.

Если установить индекс всего фрейма данных и разделить его на 80%, нет гарантии, что он даст 80% от каждого пользователя.

smple_size <- floor(0.8 * nrow(df))
train_ind <- sample(seq_len(nrow(df)), size = smple_size)

train.shared <- df[train_ind, ]
test.shared <- df[-train_ind, ]

Это даст 80% всего фрейма данных. Но каждый пользователь мог оценить разное количество фильмов.

movie_id, user_id, rated_value, feature_1, feature_2, genre, user_gender, user_ethnicity
101, 345, 3.5, 1, 1, comedy, male, white
101, 345, 3.5, 1, 2, comedy, male, white
101, 345, 3.5, 2, 1, comedy, male, white
125, 345, 4.5, 1, 4, drama, male, white
101, 233, 4.0, 1, 3, comedy, female, black
101, 233, 4.0, 2, 2, comedy, female, black
125, 233, 3.0, 1, 1, drama, female, black
125, 233, 3.0, 2, 2, drama, female, black
125, 333, 3.0, 1, 1, comedy, male, asian
125, 333, 3.0, 2, 2, comedy, male, asian 

Ответы [ 3 ]

0 голосов
/ 02 июля 2018

Это довольно легко сделать, используя dplyr:

library(dplyr)
data(iris)

iris %>%
  group_by(Species) %>%
  sample_frac(0.8)

проверить:

set.seed(1)
iris %>%
  group_by(Species) %>%
  sample_frac(0.8) %>%
  pull(Species) %>%
  table

#output
    setosa versicolor  virginica 
        40         40         40 

при исходных данных:

iris %>%
  pull(Species) %>%
  table
#output
setosa versicolor  virginica 
    50         50         50 

Хорошо, что можно group_by несколько факторов.

Базовый подход R с использованием by:

set.seed(1)
index <- as.numeric(unlist(by(seq_along(iris[,"Species"]),
                              iris[,"Species"],
                              function(x) sample(x,
                                                 size = length(x)*0.8))))

это работает?

table(iris[index,5])
#output
setosa versicolor  virginica 
    40         40         40 
0 голосов
/ 02 июля 2018

Вероятно, нет оснований не просто использовать dplyr, caret и т. Д. В большинстве случаев, но вот подход Base R

# Create example dataset
set.seed(0)
user_id <- rep(1:10, sample(1:10, 10))
df <- data.frame(user_id = user_id, vals = runif(length(user_id)))


# Sort by user id
df <- df[order(df$user_id),]
# For each user ID, Create logical index which is T for ~80% of rows
split.lgl <- lapply(unique(df$user_id), function(x){
                n.rows <- sum(df$user_id == x)
                sample(n.rows) <= 0.8*n.rows})
# subset
train <- df[do.call(c, split.lgl),]
0 голосов
/ 02 июля 2018

createDataPartition() в пакете caret может использоваться для проведения стратифицированного отбора проб. Что хорошо в этом подходе, так это то, что он позволяет вам легко получить как учебный, так и тестовый набор для построения и проверки модели:

library(caret)

sample <- caret::createDataPartition(y = df$user_id, p = 0.8, list = FALSE)

Если list = FALSE, возвращает индексы наблюдений в выборке:

in_df  <- df[sample, ]
out_df <- df[-sample, ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...