使用多个变量创建计数器

时间:2013-08-28 11:51:44

标签: r counter

我的数据如下所示:

CustomerID TripDate
1           1/3/2013
1           1/4/2013
1           1/9/2013
2           2/1/2013
2           2/4/2013
3           1/2/2013

我需要创建一个计数器变量,如下所示:

CustomerID TripDate   TripCounter
1           1/3/2013   1
1           1/4/2013   2 
1           1/9/2013   3
2           2/1/2013   1
2           2/4/2013   2 
3           1/2/2013   1 

Tripcounter将针对每位客户。

6 个答案:

答案 0 :(得分:13)

使用ave。假设您的data.frame被称为“mydf”:

mydf$counter <- with(mydf, ave(CustomerID, CustomerID, FUN = seq_along))
mydf
#   CustomerID TripDate counter
# 1          1 1/3/2013       1
# 2          1 1/4/2013       2
# 3          1 1/9/2013       3
# 4          2 2/1/2013       1
# 5          2 2/4/2013       2
# 6          3 1/2/2013       1

为了它的价值,我还在我的“splitstackshape”包中包含的函数中实现了这种方法的一个版本。该函数称为getanID

mydf <- data.frame(IDA = c("a", "a", "a", "b", "b", "b", "b"),
                   IDB = c(1, 2, 1, 1, 2, 2, 2), values = 1:7)
mydf
# install.packages("splitstackshape")
library(splitstackshape)
# getanID(mydf, id.vars = c("IDA", "IDB"))
getanID(mydf, id.vars = 1:2)
#   IDA IDB values .id
# 1   a   1      1   1
# 2   a   2      2   1
# 3   a   1      3   2
# 4   b   1      4   1
# 5   b   2      5   1
# 6   b   2      6   2
# 7   b   2      7   3

从上面的示例中可以看出,我以这样的方式编写了函数,您可以指定一个或多个应被视为ID列的列。它会检查id.vars是否有任何重复,如果是,那么它会为您生成一个新的ID变量。

答案 1 :(得分:7)

您也可以使用plyr(使用@ AnadaMahto的示例数据):

> ddply(mydf, .(IDA), transform, .id = seq_along(IDA))
  IDA IDB values .id
1   a   1      1   1
2   a   2      2   2
3   a   1      3   3
4   b   1      4   1
5   b   2      5   2
6   b   2      6   3
7   b   2      7   4

甚至:

> ddply(mydf, .(IDA, IDB), transform, .id = seq_along(IDA))
  IDA IDB values .id
1   a   1      1   1
2   a   1      3   2
3   a   2      2   1
4   b   1      4   1
5   b   2      5   1
6   b   2      6   2
7   b   2      7   3

请注意,plyr没有成为最快解决方案的声誉,因为您需要查看data.table


这是data.table方法:

library(data.table)
DT <- data.table(mydf)
DT[, .id := sequence(.N), by = "IDA,IDB"]
DT
#    IDA IDB values .id
# 1:   a   1      1   1
# 2:   a   2      2   1
# 3:   a   1      3   2
# 4:   b   1      4   1
# 5:   b   2      5   1
# 6:   b   2      6   2
# 7:   b   2      7   3

答案 2 :(得分:5)

同时,您也可以使用dplyr。如果你的data.frame被称为mydata

library(dplyr)
mydata %>% group_by(CustomerID) %>% mutate(TripCounter = row_number())

答案 3 :(得分:2)

我需要经常这样做,并编写了一个功能,它完成它与以前的答案不同。我不确定哪种解决方案最有效。

idCounter <- function(x)  {
    unlist(lapply(rle(x)$lengths, seq_len))
}

mydf$TripCounter <- idCounter(mydf$CustomerID)

答案 4 :(得分:0)

这是程序样式代码。我不相信如果你在R中使用循环那么你可能做错了什么

x <- dataframe$CustomerID
dataframe$counter <- 0
y <- dataframe$counter
count <- 1
for (i in 1:length(x)) {
  ifelse (x[i] == x[i-1], count <- count + 1, count <- 1 )
  y[i] <- count
}
dataframe$counter <- y

答案 5 :(得分:0)

这不是正确的答案,但是与for循环相比显示了一些有趣的东西,矢量化很快并不关心顺序更新。     一个&LT; -read.table(textConnection(     “CustomerID TripDate     2013年1月1日     1 1/4/2013     1 1/9/2013     2 2/1/2013     2 2/4/2013     3 1/2/2013“),header = TRUE)

a <- a %>%
group_by(CustomerID,TripDate) # must in order

res <- rep(1, nrow(a))  #base @ 1
res[2:6] <-sapply(2:6, function(i)if(a$CustomerID[i]== a$CustomerID[i - 1]) {res[i] = res[i-1]+1} else {res[i]= res[i]})
a$TripeCounter <- res