12

我的数据如下所示:

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将针对每个客户。

4

6 回答 6

14

使用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 变量。

于 2013-08-28T11:54:53.060 回答
9

您也可以使用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
于 2013-08-30T08:45:05.627 回答
7

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

library(dplyr)
mydata %>% group_by(CustomerID) %>% mutate(TripCounter = row_number())
于 2015-06-19T10:00:45.487 回答
3

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

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

mydf$TripCounter <- idCounter(mydf$CustomerID)
于 2013-08-30T08:24:12.353 回答
0

Here's the procedure styled code. I dont believe in things like if you are using loop in R then you are probably doing something wrong

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
于 2013-08-28T12:21:08.463 回答
0

这不是正确的答案,但与 for 循环相比,它显示了一些有趣的东西,矢量化速度很快,不关心顺序更新。a<-read.table(textConnection("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") ,标题=真)

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
于 2016-04-20T22:21:58.017 回答