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

如何根据R中其他列中的值添加计数列,r,sequence,R,Sequence,我有一个相对较大的数据集(16000+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

我有一个相对较大的数据集(16000+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函数rle,但不确定它是否会工作,因为白天会出现并发症。否则,我会尝试以下方法:

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

Data$site2这里有一个使用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)))

也许有一种聪明的方法可以直接做到这一点,使用各种
seq
sequence
rle
功能,但我的大脑目前有点模糊。如果您将此项保留一段时间,可能会有人提供一个光滑的非
plyr
解决方案。

使用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}))
#制作一些虚假数据
dat通过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))))

df1我只是想更新一个答案,使用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)))
库(dplyr)
#创建数据
df%
分组依据(块)%>%
变异(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
阻止站点日x站点2
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

这似乎对我混乱的数据不起作用。我忘记了站点不是完全连续的,因为某些站点的数据记录器出现故障或丢失。因此,偶尔会跳过整个数据集的站点编号,但我需要的是一个变量,该变量只需计数,这样我就可以循环使用循环函数中的索引作为分析的一部分。也许我可以尝试一下你的建议,但是使用一些聪明的功能来增加site2中以前的值,而不是基于原始的站点号。谢谢,这非常有效。我以前见过plyr,但从未使用过。ddply是完美的,我实际上是临时分开矩阵,在几天内使用重塑(=宽),应用rle(站点),然后尝试重塑(=长)。我不知道它是否有效,但我认为有大约1000种更简单的方法可以做到这一点。我喜欢dpdply解决方案。再次感谢。很好的一个,只是在一个类似的问题上尝试了ddply选项,第一次就完美地工作了