Эта проблема кажется тривиальной, но после нескольких часов чтения я теряю голову.

Мне нужно сгенерировать вектор той же длины, что и входной вектор, который перечисляет для каждого значения входного вектора общий счет для этого значения. Итак, в качестве примера я хотел бы сгенерировать последний столбец этого фрейма данных:

> df
   customer.id transaction.count total.transactions
1            1                 1                  4
2            1                 2                  4
3            1                 3                  4
4            1                 4                  4
5            2                 1                  2
6            2                 2                  2
7            3                 1                  3
8            3                 2                  3
9            3                 3                  3
10           4                 1                  1

Я понимаю, что это можно сделать двумя способами: либо используя длину пробега первого столбца, либо сгруппировав второй столбец с использованием первого и применяя максимум.

Я пробовал оба приложения:

> tapply(df$transaction.count, df$customer.id, max)

И rle:

> rle(df$customer.id)

Но оба возвращают вектор меньшей длины, чем исходный:

[1] 4  2  3  1

Любая помощь с благодарностью принята!

r
5
Angus Angus 29 Авг 2011 в 02:36

3 ответа

Лучший ответ

Вы можете сделать это без создания счетчика транзакций с помощью:

df$total.transactions <- with( df,  
                     ave( transaction.count , customer.id , FUN=length) )
6
IRTFM 29 Авг 2011 в 00:25

Вы можете использовать rle с rep, чтобы получить желаемое:

x <- rep(1:4, 4:1)
> x
 [1] 1 1 1 1 2 2 2 3 3 4

rep(rle(x)$lengths, rle(x)$lengths)
> rep(rle(x)$lengths, rle(x)$lengths)
 [1] 4 4 4 4 3 3 3 2 2 1

В целях повышения производительности вы можете сохранить объект rle отдельно, поэтому он будет вызываться только один раз.

Или, как предложил Карстен с ddply из plyr:

require(plyr)

#Expects data.frame
dat <- data.frame(x = rep(1:4, 4:1))
ddply(dat, "x", transform, total = length(x))
1
Chase 28 Авг 2011 в 23:02

Вы, вероятно, ищете подход «разделить-применить-объединить»; взгляните на ddply в пакете plyr или на функцию split в базе R.

0
Karsten W. 28 Авг 2011 в 22:49