R:如何为向量中的每个唯一值分配一个运行计数器?

时间:2014-09-25 06:00:46

标签: r

我遇到过这个问题。我想确定下个100年每个月的第二个星期日的日子。这是我的代码

x <- seq(as.Date("2014-9-01"),as.Date("2014-9-01")+100*365.25,1)

y <- format(x,"%Y%m")

xx <- NULL
for(i in unique(y)) {
  w <- which(y == i)
  xx <- c(xx,x[w[which(weekdays(x[w]) == "Sunday")[2]]])
}

head(xx)
tail(xx)

我已经实现了它但我不得不使用循环。如何使用矢量化代码更有效地完成此操作?

一般情况下,假设有一个带有 n 不同值的向量 v ,如何为每个不同的v值分配一个增加值,从每个不同的值开始为1值。也就是说,假设我从向量

开始
v <- c(1,1,1,2,2,2,2,3,4,4)

我想生成&#34;运行计数器&#34;, v.counter v

中的唯一值
v.counter <- c(1,2,3,1,2,3,4,1,1,2)
显然我可以写一个循环来做到这一点。但是我如何用矢量化代码呢?

5 个答案:

答案 0 :(得分:8)

您可以使用dplyr执行运行计数:

library(dplyr)

dat = data.frame(x=rep(1:10, each=3))

dat = dat %>%
  group_by(x) %>%
  mutate(x_count=1:n())

    x x_count
1   1       1
2   1       2
3   1       3
4   2       1
5   2       2
6   2       3
...
25  9       1
26  9       2
27  9       3
28 10       1
29 10       2
30 10       3

答案 1 :(得分:4)

对于生成组特定值,使用ave()函数应该相当简单。

ave(v, v, FUN=seq_along)
# [1] 1 2 3 1 2 3 4 1 1 2

如果您只想在v中查看连续序列而不是唯一值,那么您也可以这样做

v <- c(1,1,1,2,2,2,2,1,2,2)
ave(v, with(rle(v), rep(1:length(lengths), lengths)), FUN=seq_along)
# [1] 1 2 3 1 2 3 4 1 1 2
尽管v中只使用了两个不同的值,但

给出了相同的值。第一个解决方案将继续计算在遇到第二次时1离开的位置。另外,如果v不是数字,则可以执行

v <- rep(letters[1:4], c(3,4,1,2))
ave(seq_along(v), v, FUN=seq_along)
# [1] 1 2 3 1 2 3 4 1 1 2

仍然可以获得数值。

答案 2 :(得分:3)

假设我们有一个包含v的数据框:

data <- data.frame(v = c(1,1,1,2,2,2,2,3,4,4))

然后,使用dplyr

library(dplyr)
data %>%
    group_by(v) %>%
    mutate(v.counter = row_number())

答案 3 :(得分:2)

有很多好的答案。我留下以下内容,以获得每个月的第二个星期日,接下来的100年。我确信有更好的方法来处理日期类对象。但这也有效。

library(lubridate)
library(dplyr)
library(tidyr)

x <- seq(as.Date("2014-9-01"),as.Date("2014-9-01")+100*365.25,1)
weekday <- wday(x)
foo <- data.frame(x, weekday, stringsAsFactors = FALSE)


ana <- foo %>%
    separate(x, c("year", "month", "date"), sep = "-") %>%
    filter(weekday == 1) %>%
    group_by(year, month) %>%
    filter(row_number() == 2) %>%
    unite(sunday, year, month, date, sep = "-") %>%
    mutate(sunday = as.Date(sunday)) %>% ### If you want date object
    select(sunday) ### If you want just one column

head(ana)
Source: local data frame [6 x 1]
      sunday
1 2014-09-14
2 2014-10-12
3 2014-11-09
4 2014-12-14
5 2015-01-11
6 2015-02-08

答案 4 :(得分:1)

为了完成,我想添加data.table解决方案

dt <- data.table(x,y) dt[, wd := weekdays(x)] dt <- dt[, wdidx := seq_along(.I), by = c("y", "wd")][wd == "Sonntag" & wdidx == 2,] head(dt, 20)

“Sonntag”意味着星期日,weekdays()错综复杂的工作日回归工作日