Building on the answers of @eddi and @Rodrigo, I managed to find the following code that is a little verbose, but works. It also works if I want a more complicated ordering of events.
require(reshape2) # For acast(...)
# Input data frame
my.df <- data.frame(person = c('A', 'A', 'B', 'B', 'B', 'C'),
week = c(1, 2, 1, 3, 3, 2),
event = c('visit', 'buy', 'visit', 'visit', 'buy', 'visit'))
# Convert event into numbers, with buy > visit
the.levels <- c('visit', 'buy')
my.df$event <- as.numeric(factor(my.df$event, levels = the.levels))
# Build matrix
temp <- acast(my.df, person ~ week, function(x) {max(x)},
value.var = 'event', fill = 0)
# Convert event numbers back into text
number.to.event <- as.list(setNames(c('none', 'visit', 'buy'),
as.character(c(0, 1, 2))))
# Save row names and column names
out <- matrix(number.to.event[as.character(temp)], nrow = 3,
dimnames = dimnames(temp))
> out
1 2 3
A "visit" "buy" "none"
B "visit" "none" "buy"
C "none" "visit" "none"