Подтвердить что ты не робот

Векторизация моего мышления: векторные операции в R

Итак, раньше я ответил на свой собственный вопрос о мышлении в векторах в Р. Но теперь у меня есть еще одна проблема, которую я не могу "векторизовать". Я знаю, что векторы быстрее и медленнее, но я не могу понять, как это сделать в векторном методе:

У меня есть кадр данных (который по сентиментальным причинам мне нравится называть my.data), на который я хочу сделать полный маргинальный анализ. Мне нужно удалить определенные элементы по одному и "значение" в кадре данных, тогда мне нужно снова выполнить итерацию, удалив только следующий элемент. Затем сделайте еще раз... и снова... Идея состоит в том, чтобы сделать полный маргинальный анализ подмножества моих данных. Во всяком случае, я не могу представить, как это сделать эффективным вектором.

Я сократил фрагмент кода, и он выглядит примерно так:

for (j in my.data$item[my.data$fixed==0]) { # <-- selects the items I want to loop 
                                            #     through
    my.data.it <- my.data[my.data$item!= j,] # <-- this kicks item j out of the list
    sum.data <-aggregate(my.data.it, by=list(year), FUN=sum, na.rm=TRUE) #<-- do an
                                                                         # aggregation

    do(a.little.dance) && make(a.little.love) -> get.down(tonight) # <-- a little
                                                                   #  song and dance

    delta <- (get.love)                                         # <-- get some love
    delta.list<-append(delta.list, delta, after=length(delta.list)) #<-- put my love
                                                                    #    in a vector 
}

Так что, очевидно, я взломал кучу вещей посередине, чтобы сделать его менее неуклюжим. Целью было бы удаление j-цикла, используя что-то более эффективное вектор. Любые идеи?

4b9b3361

Ответ 1

Вот что похоже на еще один способ R-типа генерации сумм. Создайте вектор, который до тех пор, пока ваш входной вектор не содержит ничего, кроме повторяющейся суммы n элементов. Затем вычтите свой исходный вектор из вектора сумм. Результат: вектор (isums), где каждая запись - ваш исходный вектор, не содержащий i-й элемент.

> (my.data$item[my.data$fixed==0])
[1] 1 1 3 5 7
> sums <- rep(sum(my.data$item[my.data$fixed==0]),length(my.data$item[my.data$fixed==0]))
> sums
[1] 17 17 17 17 17
> isums <- sums - (my.data$item[my.data$fixed==0])
> isums
[1] 16 16 14 12 10

Ответ 2

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

data = ...;
items = ...;

leave_one_out = function(i) {
   data1 = data[items != i];
   delta = ...;  # some operation on data1
   return delta;
}


for (j in items) {
   delta.list = cbind(delta.list, leave_one_out(j));
}

Для векторизации все, что вы делаете, заменяет цикл for функцией отображения sapply:

delta.list = sapply(items, leave_one_out);

Ответ 3

Это не ответ, но мне интересно, есть ли проницательность в этом направлении:

> tapply((my.data$item[my.data$fixed==0])[-1], my.data$year[my.data$fixed==0][-1], sum)

tapply создает таблицу статистики (суммы в этом случае, третий аргумент), сгруппированные по параметру, указанному в качестве второго аргумента. Например

2001 2003 2005 2007
1    3    5    7

Обозначение [-1] уменьшает наблюдение (строку) одного из выбранных строк. Таким образом, вы можете использовать цикл [-i] для каждого цикла

for (i in 1:length(my.data$item)) {
  tapply((my.data$item[my.data$fixed==0])[-i], my.data$year[my.data$fixed==0][-i], sum)
}

имея в виду, что если у вас есть годы с одним наблюдением, тогда таблицы, возвращаемые последовательными вызовами, не будут иметь одинаковое количество столбцов. (т.е. если вы оставите единственное наблюдение за 2001 год, то в 2003, 2005 и 2007 годах будут возвращены только те столбцы).