Есть ли способ привязать данные к data.frame по некоторому индексу? - PullRequest
2 голосов
/ 28 февраля 2011
#For say, I got a situation like this
user_id = c(1:5,1:5)
time = c(1:10)
visit_log = data.frame(user_id, time)

#And I've wrote a method to calculate interval
interval <- function(data) {
    interval = c(Inf)
    for (i in seq(1, length(data$time))) {
        intv = data$time[i]-data$time[i-1]
        interval = append(interval, intv)
    }

    data$interval = interval
    return (data)
}

#But when I want to get intervals by user_id and bind them to the data.frame,
#I can't find a proper way
#Is there any method to get something like
new_data = merge(by(visit_log, INDICE=visit_log$user_id, FUN=interval))

#And the result should be
    user_id time interval
1        1    1      Inf
2        2    2      Inf
3        3    3      Inf
4        4    4      Inf
5        5    5      Inf
6        1    6        5
7        2    7        5
8        3    8        5
9        4    9        5
10       5   10        5

1 Ответ

3 голосов
/ 28 февраля 2011

Мы можем заменить ваш цикл функцией diff(), которая вычисляет различия между смежными индексами в векторе, например:

> diff(c(1,3,6,10))
[1] 2 3 4

К этому мы можем добавить Inf к различиям через c(Inf, diff(x)).

Следующее, что нам нужно, это применить вышеуказанное к каждому user_id индивидуально.Для этого есть много вариантов, но здесь я использую aggregate().Смущает, что эта функция возвращает фрейм данных с компонентом time, который сам является матрицей.Нам нужно преобразовать эту матрицу в вектор, опираясь на тот факт, что в R столбцы матриц заполняются первыми.Наконец, мы добавляем и interval столбец к входным данным в соответствии с вашей исходной версией функции.

interval <- function(x) {
    diffs <- aggregate(time ~ user_id, data = x, function(y) c(Inf, diff(y)))
    diffs <- as.numeric(diffs$time)
    x <- within(x, interval <- diffs)
    x
}

Вот немного расширенный пример с 3 временными точками на пользователя, чтобы проиллюстрировать вышеуказанную функцию:

> visit_log = data.frame(user_id = rep(1:5, 3), time  = 1:15)
> interval(visit_log)
   user_id time interval
1        1    1      Inf
2        2    2      Inf
3        3    3      Inf
4        4    4      Inf
5        5    5      Inf
6        1    6        5
7        2    7        5
8        3    8        5
9        4    9        5
10       5   10        5
11       1   11        5
12       2   12        5
13       3   13        5
14       4   14        5
15       5   15        5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...