如何根据R中其他列中的值添加计数列

时间:2011-12-18 04:22:36

标签: r sequence

我有一个相对较大的数据集(16,000 + x~31)。换句话说,它足够大,我不想在Excel中逐行操作它。数据采用以下形式:

block  site     day  X1   X2
1      1        1    0.4  5.1 
1      1        2    0.8  1.1
1      1        3    1.1  4.2
1      2        1    ...  ...
1      2        2
1      2        3
2      3        1
2      3        2
2      3        3
2      4        1
2      4        2
2      4        3

正如您所看到的,网站计数是连续的,但我想要一个列,其中站点编号与每个块重置。例如,我想要下面这样的东西:

block  site     day  X1   X2    site2
1      1        1    0.4  5.1   1
1      1        2    0.8  1.1   1
1      1        3    1.1  4.2   1
1      2        1    ...  ...   2
1      2        2               2
1      2        3               2
2      3        1               1
2      3        2               1
2      3        3               1
2      4        1               2
2      4        2               2
2      4        3               2

我正在考虑使用R功能但是我不确定它是否会因为白天的并发症而起作用。否则,我会尝试类似的事情:

Data$site2 <- sequence(rle(Data$block)$lengths)

是否有人建议添加列计数(序列)每个块内的网站数量?如果有帮助,每个站点记录的天数(263)相同,但每个站点的站点数量不同。

4 个答案:

答案 0 :(得分:6)

使用 plyr ddply,这是一个略显笨拙的解决方案:

ddply(df,.(block),transform,
                  site1 = rep(1:length(unique(site)),
                             times = rle(site)$lengths))

或略微光滑的版本:

ddply(df,.(block),transform,site1 = as.integer(as.factor(site)))

但是,使用各种seqsequencerle函数可能会有一种巧妙的方法直接执行此操作,但此刻我的大脑有点朦胧。如果你把这个打开一点,有人可能会带来一个光滑的非plyr解决方案。

答案 1 :(得分:1)

使用tapply可以正常工作

# Make some fake data
dat <- data.frame(block = rep(1:3, each = 4), site = rep(1:6, each  = 2), val = rnorm(12))
# For each block reset the count
dat$site2 <- unlist(tapply(dat$site, dat$block, function(x){x - min(x) + 1}))

答案 2 :(得分:0)

通过ave:

df1 <- structure(list(block = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2), 
    site = c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4), day = c(1, 
    2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)), .Names = c("block", "site", 
"day"), row.names = c("2", "3", "4", "5", "6", "7", "8", "9", 
"10", "11", "12", "13"), class = "data.frame")

df1$site2 <- ave(df1$site,df1$block,FUN=function(x) match(x,sort(unique(x))))

答案 3 :(得分:0)

我只是想使用dplyr更新一个答案,以实现@joran的方法为现在发现这个问题的人。

library(dplyr)

# create data
df <- data.frame(block = rep(1:3, each = 4), 
                 site = rep(1:6, each  = 2), 
                 day = rep(1:2, times = 6), 
                 x = rnorm(12))

df %>%
  group_by(block) %>%
  mutate(site2 = as.integer(as.factor(site)))

结果输出为:

block  site   day     x    site2
<int> <int> <int>  <dbl>   <int>
1     1       1    0.762     1
1     1       2   -0.612     1
1     2       1    1.06      2
1     2       2   -0.168     2
2     3       1    1.09      1
2     3       2    1.38      1
2     4       1    1.69      2
2     4       2    0.414     2
3     5       1    0.208     1
3     5       2   -0.647     1
3     6       1   -1.01      2
3     6       2   -0.354     2