Как создать уникальные образцы (каждый элемент появляется только в одном образце), используя R? - PullRequest
1 голос
/ 09 ноября 2019

Я работаю с моделью BTYD для составления прогноза будущих транзакций клиента. К сожалению, из-за использования методов mcmc я не могу выполнить прогноз для всей моей базы клиентов (сотни тысяч), поэтому мне приходится разбивать базу на множество случайных выборок и выполнять несколько прогонов этой модели для каждой из них, чтобы получитьпрогноз.

Моя идея заключалась в том, чтобы использовать цикл для выполнения следующих действий:

  1. для получения случайной выборки длиной 10000 из всей базы (назовем этот фрейм данных «данными»). )
  2. сохранить результат в объекте с именем "sample1"
  3. Теперь мы должны вернуться к "данным" и исключить клиентов, которые находятся в "sample1", и сохранить новый результат в "данных"".
  4. получить новую случайную выборку (" sample2 ") из новых" data "
  5. создать новую версию" data ", исключая всех клиентов, включенных в" sample2 "(и" sample1 "").
  6. ... продолжайте этот цикл, пока мы не закончим базу и не создадим N выборок, которые содержат всю базу.

(Каждый идентификатор должен быть только в одной выборке).

к сожалению мойкажется, код работает не так, как я хочу (на данный момент я не очень хорошо разбираюсь с циклами.


getwd()

data<-read.csv("MOCK_DATA (1).csv") 
# this is a fake dataset of 1000 rows that contains only 2 columns: 
# customer ID (column name: "id") and a random number (column name "value").
# Every customer ID appears only once in the dataset.

head(data)

set.sample.size<-100
num.cycles<-ceiling(nrow(data)/set.sample.size)

for(i in 1:(num.cycles)) {
 nam <- paste("sample_", i, sep = "")
 assign(nam, data[sample(nrow(data), set.sample.size), ])
 data<-data[!(data$id %in% nam$id),]
}

Этот код генерирует следующую ошибку: Ошибка в nam $ id: $ operator isнедопустимо для атомарных векторов

Я ожидаю получить 10 объектов с именем "sample_1" .. "sample_10", каждый из которых состоит из 100 случайных идентификаторов из исходных данных, но все уникальные (никакие идентификаторы не разделяются между 10образцы).

Ответы [ 3 ]

2 голосов
/ 09 ноября 2019

Рассмотрите возможность случайного переупорядочения целых данных по идентификатору, а затем деления на строки равной длины. Конечным результатом будет один именованный список из множества фреймов данных вместо множества отдельных объектов, заполняющих вашу глобальную среду.

set.seed(11092019)

# RE-ORDER DATA FRAME (SAME LENGTH)
data <- with(data, data[order(sample(id, nrow(data))),])

# BUILD A LIST OF DFs 
set.sample.size <- 100
data$cycles_group <- paste0("sample_", ceiling(1:nrow(data)/set.sample.size))

df_list <- split(data, data$cycles_group)

# RETRIEVE INDIVIDUAL DF BY NAME
df_list$sample_1#
df_list$sample_2#
df_list$sample_3#
...

В качестве альтернативы, с помощью by вы можете разделить выборки и выполнить каждое подмножество через любой из ваших BTYDмодель процесса (аналогично split + lapply):

results_list <- by(data, data$cycles_group, function(sub_df) {
   # ... do something with sub_df ...
})
1 голос
/ 09 ноября 2019

Вот компактный способ получить список выборок, используя mtcars в качестве набора данных без использования явного цикла, с размером выборки = 8:

n <- nrow(mtcars)
s <- sample(1:n, replace=FALSE)
sampsize <- 8
nsamps <- n / sampsize
m <- matrix(s, nrow = sampsize)
samps <- lapply(1:nsamps, function(x) mtcars[m[, x], ] )

Строки случайным образом выбираются неявно с использованием вектораs. Матрица m содержит векторы случайных чисел.

1 голос
/ 09 ноября 2019

Вот воспроизводимый пример с использованием iris набора данных

set.sample.size<-10

num.cycles<-ceiling(nrow(iris)/set.sample.size)


iris$id <- 1:150 


for(i in 1:(num.cycles)) {
  nam <- paste("sample_", i, sep = "")
  assign(nam, iris[sample(nrow(iris), set.sample.size), ])
  iris<-iris[!(iris$id %in% get(nam)$id),]
}

Единственная проблема в вашем коде - nam$id не имеет смысла, так как nam - это просто строка (имяфрейм данных, а не сам фрейм данных)

...