我有一个数据框(all_data),其中我有一个网站列表(1 ...到n)和他们的分数,例如
site score
1 10
1 11
1 12
4 10
4 11
4 11
8 9
8 8
8 7
Run Code Online (Sandbox Code Playgroud)
我想创建一个列,按照数字顺序对每个级别的站点进行编号,就像一个计数器.在该示例中,站点(1,4和8)将在"数字"列中具有1到3的相应计数器:
site score number
1 10 1
1 11 1
1 12 1
4 10 2
4 11 2
4 11 2
8 9 3
8 8 3
8 7 3
Run Code Online (Sandbox Code Playgroud)
我相信这一定很容易解决,但我还没有找到办法.
Jor*_*eys 18
尝试 Data$number <- as.numeric(as.factor(Data$site))
旁注:我和@Chase的解决方案与另一方面@DWin的解决方案之间的区别在于数字的排序.双方as.factor并factor会水平自动排序,而不会在@DWin的解决方案发生:
Dat <- data.frame(site = rep(c(1,8,4), each = 3), score = runif(9))
Dat$number <- as.numeric(factor(Dat$site))
Dat$sitenum <- match(Dat$site, unique(Dat$site) )
Run Code Online (Sandbox Code Playgroud)
给
> Dat
site score number sitenum
1 1 0.7377561 1 1
2 1 0.3131139 1 1
3 1 0.7862290 1 1
4 8 0.4480387 3 2
5 8 0.3873210 3 2
6 8 0.8778102 3 2
7 4 0.6916340 2 3
8 4 0.3033787 2 3
9 4 0.6552808 2 3
Run Code Online (Sandbox Code Playgroud)
42-*_*42- 13
这应该是相当有效和可理解的:
Dat$sitenum <- match(Dat$site, unique(Dat$site))
Run Code Online (Sandbox Code Playgroud)
Jaa*_*aap 13
另外两个选择:
1)使用包中的.GRP功能data.table:
library(data.table)
setDT(dat)[, num := .GRP, by = site]
Run Code Online (Sandbox Code Playgroud)
使用下面的示例数据集,结果如下:
> dat
site score num
1: 1 0.14945795 1
2: 1 0.60035697 1
3: 1 0.94643075 1
4: 8 0.68835336 2
5: 8 0.50553372 2
6: 8 0.37293624 2
7: 4 0.33580504 3
8: 4 0.04825135 3
9: 4 0.61894754 3
10: 8 0.96144729 2
11: 8 0.65496051 2
12: 8 0.51029199 2
Run Code Online (Sandbox Code Playgroud)
2)使用以下group_indices功能dplyr:
dat$num <- group_indices(dat, site)
Run Code Online (Sandbox Code Playgroud)
或者当您想要解决非标准评估时:
library(dplyr)
dat %>%
mutate(num = group_indices_(dat, .dots = c('site')))
Run Code Online (Sandbox Code Playgroud)
这导致:
site score num
1 1 0.42480366 1
2 1 0.98736177 1
3 1 0.35766187 1
4 8 0.06243182 3
5 8 0.55617002 3
6 8 0.20304632 3
7 4 0.90855921 2
8 4 0.25215078 2
9 4 0.44981251 2
10 8 0.60288270 3
11 8 0.46946587 3
12 8 0.44941782 3
Run Code Online (Sandbox Code Playgroud)
可以看出,dplyr给出了组号的不同顺序.
如果每次更改组时都需要其他数字,还有其他几个选项:
1)基础R:
# option 1:
dat$num <- cumsum(c(TRUE, head(dat$site, -1) != tail(dat$site, -1)))
# option 2:
x <- rle(dat$site)$lengths
dat$num <- rep(seq_along(x), times=x)
Run Code Online (Sandbox Code Playgroud)
2)与所述data.table包:
library(data.table)
setDT(dat)[, num := rleid(site)]
Run Code Online (Sandbox Code Playgroud)
这一切都导致:
> dat
site score num
1 1 0.80817855 1
2 1 0.07881334 1
3 1 0.60092828 1
4 8 0.71477988 2
5 8 0.51384565 2
6 8 0.72011650 2
7 4 0.74994627 3
8 4 0.09564052 3
9 4 0.39782587 3
10 8 0.29446540 4
11 8 0.61725367 4
12 8 0.97427413 4
Run Code Online (Sandbox Code Playgroud)
使用数据:
dat <- data.frame(site = rep(c(1,8,4,8), each = 3), score = runif(12))
Run Code Online (Sandbox Code Playgroud)
在新的dplyr1.0.0 中,我们可以使用cur_group_id()它为组提供唯一的数字标识符。
library(dplyr)
df %>% group_by(site) %>% mutate(number = cur_group_id())
# site score number
# <int> <int> <int>
#1 1 10 1
#2 1 11 1
#3 1 12 1
#4 4 10 2
#5 4 11 2
#6 4 11 2
#7 8 9 3
#8 8 8 3
#9 8 7 3
Run Code Online (Sandbox Code Playgroud)
数据
df <- structure(list(site = c(1L, 1L, 1L, 4L, 4L, 4L, 8L, 8L, 8L),
score = c(10L, 11L, 12L, 10L, 11L, 11L, 9L, 8L, 7L)),
class = "data.frame", row.names = c(NA, -9L))
Run Code Online (Sandbox Code Playgroud)
使用来自@Jaap 的数据,使用的另一种dplyr可能性dense_rank()可能是:
dat %>%
mutate(ID = dense_rank(site))
site score ID
1 1 0.1884490 1
2 1 0.1087422 1
3 1 0.7438149 1
4 8 0.1150771 3
5 8 0.9978203 3
6 8 0.7781222 3
7 4 0.4081830 2
8 4 0.2782333 2
9 4 0.9566959 2
10 8 0.2545320 3
11 8 0.1201062 3
12 8 0.5449901 3
Run Code Online (Sandbox Code Playgroud)
或者类似rleid()的dplyr方法,首先排列数据:
dat %>%
arrange(site) %>%
mutate(ID = with(rle(site), rep(seq_along(lengths), lengths)))
site score ID
1 1 0.1884490 1
2 1 0.1087422 1
3 1 0.7438149 1
4 4 0.4081830 2
5 4 0.2782333 2
6 4 0.9566959 2
7 8 0.1150771 3
8 8 0.9978203 3
9 8 0.7781222 3
10 8 0.2545320 3
11 8 0.1201062 3
12 8 0.5449901 3
Run Code Online (Sandbox Code Playgroud)
或使用duplicated()和cumsum():
df %>%
mutate(ID = cumsum(!duplicated(site)))
Run Code Online (Sandbox Code Playgroud)
与base R以下相同:
df$ID <- with(rle(df$site), rep(seq_along(lengths), lengths))
Run Code Online (Sandbox Code Playgroud)
或者:
df$ID <- cumsum(!duplicated(df$site))
Run Code Online (Sandbox Code Playgroud)