Использование apply и rbind для построения R data.frame - PullRequest
1 голос
/ 17 сентября 2011

У меня есть существующий data.frame, который содержит некоторые начальные значения. Что я хочу сделать, это создать еще один data.frame, который имеет 10 случайно выбранных строк для каждой строки в первом data.frame. Также я пытаюсь сделать это в стиле R, поэтому я бы хотел избежать итерации.

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

Вот мой прогресс на данный момент:

Пример данных:

   starts <- structure(list(instance = structure(21:26, .Label = c("big_1", 
   "big_10", "big_11", "big_12", "big_13", "big_14", "big_15", "big_16", 
   "big_17", "big_18", "big_19", "big_2", "big_20", "big_3", "big_4", 
   "big_5", "big_6", "big_7", "big_8", "big_9", "competition01", 
   "competition02", "competition03", "competition04", "competition05", 
   "competition06", "competition07", "competition08", "competition09", 
   "competition10", "competition11", "competition12", "competition13", 
   "competition14", "competition15", "competition16", "competition17", 
   "competition18", "competition19", "competition20", "med_1", "med_10", 
   "med_11", "med_12", "med_13", "med_14", "med_15", "med_16", "med_17", 
   "med_18", "med_19", "med_2", "med_20", "med_3", "med_4", "med_5", 
   "med_6", "med_7", "med_8", "med_9", "small_1", "small_10", "small_11", 
   "small_12", "small_13", "small_14", "small_15", "small_16", "small_17", 
   "small_18", "small_19", "small_2", "small_20", "small_3", "small_4", 
   "small_5", "small_6", "small_7", "small_8", "small_9"), class = "factor"), 
   event.clashes = c(674L, 626L, 604L, 1036L, 991L, 929L), overlaps = c(0L, 
   0L, 0L, 0L, 0L, 0L), room.valid = c(324L, 320L, 268L, 299L, 
   294L, 220L), final.timeslot = c(0L, 0L, 0L, 0L, 0L, 0L), 
   three.in.a.row = c(246L, 253L, 259L, 389L, 365L, 430L), single.event = c(97L, 
   120L, 97L, 191L, 150L, 138L)), .Names = c("instance", "event.clashes", 
   "overlaps", "room.valid", "final.timeslot", "three.in.a.row", 
   "single.event"), row.names = c(NA, 6L), class = "data.frame")

Код:

   library(reshape)
   m.starts <- melt(starts)

   df <- data.frame()

   gen.data <- function(x){
       inst <- x[1]
       constr <- x[2]
       v <- as.integer(x[3])
       val <- as.integer(rnorm(1, max(0, v), v / 2))
       # Should probably return a data.frame here
       print(paste(inst, constr, val))
   }

   apply(m.starts, 1, gen.data)

Ответы [ 3 ]

6 голосов
/ 17 сентября 2011

Мне неясно, что вы на самом деле делаете, но следующие изменения в вашей функции gen_data, кажется, делают то, что вы хотите.В частности, мне не ясно, что вы делаете с val, поскольку это, по-видимому, просто генерирует случайное число со средним значением столбца значения для этой строки и стандартным отклонением этого значения, деленным на два.Это то, что вы хотите?Я добавил новый параметр в вашу функцию, чтобы учесть количество строк, которые вы хотите сгенерировать:

gen.data <- function(x, nreps = 10){
    inst <- x[1]
        constr <- x[2]
        v <- as.integer(x[3])
        val <- as.integer(rnorm(nreps, max(0, v), v / 2))

        out <- data.frame(inst = rep(inst, nreps)
            , constr = rep(constr, nreps)
         , val = val)

    return(out)
       }

И затем используется:

do.call("rbind", apply(m.starts, 1, gen.data))

Результат:

             inst         constr  val
1   competition01  event.clashes  876
2   competition01  event.clashes  714
3   competition01  event.clashes  912
4   competition01  event.clashes  -46
5   competition01  event.clashes  369
....
....
357 competition06   single.event  149
358 competition06   single.event  248
359 competition06   single.event  128
360 competition06   single.event  168
1 голос
/ 17 сентября 2011

Нет необходимости в apply или rbind.Все, что требуется, это простое подмножество векторов:

samples <- sample(1:nrow(starts), nrow(starts)*10, replace=TRUE)
starts[samples, 1:3]

Первые 5 строк результатов:

> head(starts[samples, 1:3], 5)

         instance event.clashes overlaps
2   competition02           626        0
5   competition05           991        0
6   competition06           929        0
4   competition04          1036        0
2.1 competition02           626        0
0 голосов
/ 17 сентября 2011

Вы можете объединить идеи решений Андри и Чейза следующим образом:

#Repeat each row ten times
start.m1 <- start.m[rep(1:nrow(start.m),each = 10),]

#Create extended vector to use to define 
# means/sd
m <- rep(start.m$value,each = 10)

#Remove negative values; 
# although none were in your data
m[m <= 0] <- 0

#Replace value with rnorm values
start.m1$value <- rnorm(nrow(start.m1), mean = m, sd = m / 2)

, что приводит к чему-то похожему на это:

> head(start.m1)
         instance      variable     value
1   competition01 event.clashes 1098.0220
1.1 competition01 event.clashes 1208.4304
1.2 competition01 event.clashes  883.7976
1.3 competition01 event.clashes  365.1396
1.4 competition01 event.clashes  862.3113
1.5 competition01 event.clashes 1352.7085

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...