2013-08-28 26 views
9

Tôi có dữ liệu của tôi trông giống như dưới đây:Tạo truy cập với nhiều biến

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 

tôi cần phải tạo một biến truy cập, trong đó sẽ như thế nào dưới đây:

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 sẽ cho mỗi khách hàng.

Trả lời

12

Sử dụng ave. Giả sử data.frame được gọi là "mydf" của bạn:

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 

Đối với những gì nó có giá trị, tôi cũng thực hiện một phiên bản của phương pháp này trong một chức năng có trong tôi gói "splitstackshape". Hàm được gọi 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 

Như bạn có thể nhìn thấy từ ví dụ trên, tôi đã viết các chức năng trong một cách mà bạn có thể chỉ định một hoặc nhiều cột đó phải được coi là cột ID. Nó kiểm tra xem có bất kỳ số nào trong số id.vars được sao chép hay không và nếu có, thì nó sẽ tạo biến ID mới cho bạn.

+0

Cảm ơn rất nhiều Ananda !, Công trình này! – kaos1511

0

Đây là mã theo thủ tục. Tôi không tin vào những thứ như nếu bạn đang sử dụng vòng lặp trong R thì có thể bạn đang làm sai điều gì đó

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 
+1

Có thể bạn không làm điều gì đó sai, nhưng chắc chắn bạn sẽ làm điều gì đó chậm chạp. – juba

+1

Và tôi muốn một lớp lót @AnandaMahto hơn 9 dòng mã của bạn. –

+1

hóa ra, tôi cũng thích một lớp lót và tôi chắc chắn sẽ là điểm chuẩn để thấy sự chậm chạp của tôi –

2

Tôi cần thực hiện điều này thường xuyên và viết một hàm hoàn thành khác với câu trả lời trước. Tôi không chắc giải pháp nào hiệu quả nhất.

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

mydf$TripCounter <- idCounter(mydf$CustomerID) 
+0

Điều này là không chính xác. Bạn có nghĩa là để sử dụng 'chuỗi' đó là * rất khác nhau * từ' seq_along'. – A5C1D2H2I1M1N2O1R2T1

+0

Hãy thử thay vào đó: 'idCounter <- function (x) sequence (rle (x) $ lengths) ' – A5C1D2H2I1M1N2O1R2T1

+0

@Ananda, Cảm ơn bạn đã bắt được điều này, tôi đã vô tình gõ" seq_along "thay vì" seq_len "(hiện đã được sửa ở trên). Tôi không quen thuộc với 'chuỗi', và nhìn vào' sequence' Tôi thấy rằng định nghĩa hàm của tôi tương tự như 'sequence' (tức là,' sequence <- function (nvec) unlist (lapply (nvec, seq_len)) '), ngoại trừ tôi đã thay thế 'nvec' bằng' rle (x) $ lengths'. Sử dụng 'trình tự' trực tiếp chắc chắn là thanh lịch hơn; tuy nhiên, là một người dùng R tương đối mới, tôi thấy phiên bản dài hơn của tôi hữu ích vì tôi có thể thực hiện tốt hơn các bước liên quan. – RayB

7

Bạn cũng có thể sử dụng plyr cho điều này (sử dụng @ dữ liệu ví dụ AnadaMahto của):

> 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 

hoặc thậm chí:

> 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 

Lưu ý rằng plyr không có một danh tiếng cho là giải pháp nhanh nhất, cho rằng bạn cần phải xem qua data.table.


Dưới đây là một cách tiếp cận 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 
+0

Tôi chưa bao giờ làm việc với 'data.table', chỉ nghe về sự huy hoàng và vinh quang của nó :). –

+0

@PaulHiemstra Nhưng bạn đã làm việc với nó. Chỉ một lần thôi sao? http://www.r-statistics.com/2011/08/comparison-of-ave-ddply-and-data-table/ –

+0

Đó là một thử nghiệm nhỏ mà tôi đã sao chép từ người khác, xem bài đăng SO được đề cập trong bài đăng đó. Tôi đã có ý nghĩa để tìm hiểu data.table, nhưng chưa bao giờ cảm thấy nhu cầu thực sự. Có lẽ dữ liệu của tôi không đủ lớn :). –

5

Trong khi đó, bạn cũng có thể sử dụng dplyr. nếu data.frame của bạn được gọi là mydata

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

Đây không phải là câu trả lời đúng nhưng cho thấy một số điều thú vị so với vòng lặp, vector hóa nhanh không quan tâm đến việc cập nhật tuần tự. một < -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 "), tiêu đề = 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