R 对数据框中组内的行进行编号
使用与此类似的数据帧:R 对数据框中组内的行进行编号,r,dataframe,r-faq,R,Dataframe,R Faq,使用与此类似的数据帧: set.seed(100) df <- data.frame(cat = c(rep("aaa", 5), rep("bbb", 5), rep("ccc", 5)), val = runif(15)) df <- df[order(df$cat, df$val), ] df cat val 1 aaa 0.05638315 2 aaa 0.25767250 3 aaa 0.3077
set.seed(100)
df <- data.frame(cat = c(rep("aaa", 5), rep("bbb", 5), rep("ccc", 5)), val = runif(15))
df <- df[order(df$cat, df$val), ]
df
cat val
1 aaa 0.05638315
2 aaa 0.25767250
3 aaa 0.30776611
4 aaa 0.46854928
5 aaa 0.55232243
6 bbb 0.17026205
7 bbb 0.37032054
8 bbb 0.48377074
9 bbb 0.54655860
10 bbb 0.81240262
11 ccc 0.28035384
12 ccc 0.39848790
13 ccc 0.62499648
14 ccc 0.76255108
15 ccc 0.88216552
set.seed(100)
df使用ave
、ddply
、dplyr
或数据。表
:
df$num <- ave(df$val, df$cat, FUN = seq_along)
df$num <- sequence(rle(df$cat)$lengths)
> set.seed(100)
> df <- data.frame(cat = c(rep("aaa", 5), rep("bbb", 5), rep("ccc", 5)), val = runif(15))
> df <- df[order(df$cat, df$val), ]
> df$num <- data.table::rowid(df$cat)
> df
cat val num
4 aaa 0.05638315 1
2 aaa 0.25767250 2
1 aaa 0.30776611 3
5 aaa 0.46854928 4
3 aaa 0.55232243 5
10 bbb 0.17026205 1
8 bbb 0.37032054 2
6 bbb 0.48377074 3
9 bbb 0.54655860 4
7 bbb 0.81240262 5
13 ccc 0.28035384 1
14 ccc 0.39848790 2
11 ccc 0.62499648 3
15 ccc 0.76255108 4
12 ccc 0.88216552 5
或:
或者(内存效率最高,在DT
中通过引用分配):
库(data.table)
DT这里有一个选项,使用按组循环,而不是按行循环(像OP那样)
for(i in unique(df$cat))df$num[df$cat==i]为了使这个问题更完整,一个带有序列和rle的基本R替代方案:
df$num <- ave(df$val, df$cat, FUN = seq_along)
df$num <- sequence(rle(df$cat)$lengths)
> set.seed(100)
> df <- data.frame(cat = c(rep("aaa", 5), rep("bbb", 5), rep("ccc", 5)), val = runif(15))
> df <- df[order(df$cat, df$val), ]
> df$num <- data.table::rowid(df$cat)
> df
cat val num
4 aaa 0.05638315 1
2 aaa 0.25767250 2
1 aaa 0.30776611 3
5 aaa 0.46854928 4
3 aaa 0.55232243 5
10 bbb 0.17026205 1
8 bbb 0.37032054 2
6 bbb 0.48377074 3
9 bbb 0.54655860 4
7 bbb 0.81240262 5
13 ccc 0.28035384 1
14 ccc 0.39848790 2
11 ccc 0.62499648 3
15 ccc 0.76255108 4
12 ccc 0.88216552 5
如果df$cat
是一个因子变量,则需要将其包装为.character
首先:
df$num <- sequence(rle(as.character(df$cat))$lengths)
df$num我想使用rank()
函数添加一个data.table
变量,它提供了更改顺序的额外可能性,因此比seq_len()
解决方案更灵活,与RDBMS中的行数函数非常类似
# Variant with ascending ordering
library(data.table)
dt <- data.table(df)
dt[, .( val
, num = rank(val))
, by = list(cat)][order(cat, num),]
cat val num
1: aaa 0.05638315 1
2: aaa 0.25767250 2
3: aaa 0.30776611 3
4: aaa 0.46854928 4
5: aaa 0.55232243 5
6: bbb 0.17026205 1
7: bbb 0.37032054 2
8: bbb 0.48377074 3
9: bbb 0.54655860 4
10: bbb 0.81240262 5
11: ccc 0.28035384 1
12: ccc 0.39848790 2
13: ccc 0.62499648 3
14: ccc 0.76255108 4
# Variant with descending ordering
dt[, .( val
, num = rank(desc(val)))
, by = list(cat)][order(cat, num),]
#具有升序的变体
库(数据表)
dt这里有一个小的改进技巧,允许在组内排序“val”:
# 1. Data set
set.seed(100)
df <- data.frame(
cat = c(rep("aaa", 5), rep("ccc", 5), rep("bbb", 5)),
val = runif(15))
# 2. 'dplyr' approach
df %>%
arrange(cat, val) %>%
group_by(cat) %>%
mutate(id = row_number())
#1。数据集
种子集(100)
df%
排列(类别,val)%>%
分组依据(类别)%>%
变异(id=行号()
另一种可能性是:
df %>%
group_by(cat) %>%
mutate(num = 1:n())
cat val num
<fct> <dbl> <int>
1 aaa 0.0564 1
2 aaa 0.258 2
3 aaa 0.308 3
4 aaa 0.469 4
5 aaa 0.552 5
6 bbb 0.170 1
7 bbb 0.370 2
8 bbb 0.484 3
9 bbb 0.547 4
10 bbb 0.812 5
11 ccc 0.280 1
12 ccc 0.398 2
13 ccc 0.625 3
14 ccc 0.763 4
15 ccc 0.882 5
df%>%
分组依据(类别)%>%
变异(num=1:n())
猫瓦尔数
1 aaa 0.0564 1
2 aaa 0.258 2
3 aaa 0.308 3
4 aaa 0.469 4
5 aaa 0.552 5
6 bbb 0.170 1
7 bbb 0.370 2
8 bbb 0.484 3
9 bbb 0.547 4
10 bbb 0.812 5
11 ccc 0.280 1
12 ccc 0.398 2
13 ccc 0.625 3
14 ccc 0.763 4
15 ccc 0.882 5
使用数据中的rowid()
函数。表
:
df$num <- ave(df$val, df$cat, FUN = seq_along)
df$num <- sequence(rle(df$cat)$lengths)
> set.seed(100)
> df <- data.frame(cat = c(rep("aaa", 5), rep("bbb", 5), rep("ccc", 5)), val = runif(15))
> df <- df[order(df$cat, df$val), ]
> df$num <- data.table::rowid(df$cat)
> df
cat val num
4 aaa 0.05638315 1
2 aaa 0.25767250 2
1 aaa 0.30776611 3
5 aaa 0.46854928 4
3 aaa 0.55232243 5
10 bbb 0.17026205 1
8 bbb 0.37032054 2
6 bbb 0.48377074 3
9 bbb 0.54655860 4
7 bbb 0.81240262 5
13 ccc 0.28035384 1
14 ccc 0.39848790 2
11 ccc 0.62499648 3
15 ccc 0.76255108 4
12 ccc 0.88216552 5
>设置种子(100)
>df$num df
猫瓦尔数
4 aaa 0.05638315 1
2 aaa 0.25767250 2
1 aaa 0.30776611 3
5 aaa 0.46854928 4
3 aaa 0.55232243 5
10桶0.17026205 1
8 bbb 0.37032054 2
6 bbb 0.48377074 3
9 bbb 0.54655860 4
7 bbb 0.81240262 5
13 ccc 0.28035384 1
14 ccc 0.39848790 2
11 ccc 0.62499648 3
15 ccc 0.76255108 4
12 ccc 0.88216552 5
另一个基本R解决方案是按照cat
拆分数据帧,然后使用lapply
:添加一个编号为1:nrow(x)
的列。最后一步是使用do.call
返回最终数据帧,即:
df_split <- split(df, df$cat)
df_lapply <- lapply(df_split, function(x) {
x$num <- seq_len(nrow(x))
return(x)
})
df <- do.call(rbind, df_lapply)
df_split非常简单、整洁的解决方案
整个数据帧的行号
库(tidyverse)
虹膜%>%
变异(行数=沿萼片长度排列))%>%
头
萼片。长萼片。宽花瓣。长花瓣。宽种行数
1 5.1 3.5 1.4 0.2 1
2 4.9 3.0 1.4 0.2 setosa 2
3 4.7 3.2 1.3 0.2 3
.. ... ... ... ... ...... ...
148 6.5 3.0 5.2 2.0弗吉尼亚州148
149 6.2 3.4 5.4 2.3弗吉尼亚州149
150 5.9 3.0 5.1 1.8弗吉尼亚州150
数据框中分组的行号
iris%>%
组别(种类)%>%
变异(群体中的数量=沿着(物种)的顺序))%>%
as.data.frame
萼片。长萼片。宽花瓣。长花瓣。宽种数
1 5.1 3.5 1.4 0.2 1
2 4.9 3.0 1.4 0.2 setosa 2
3 4.7 3.2 1.3 0.2 3
.. ... ... ... ... ...... ..
48 4.6 3.2 1.4 0.2刚毛48
49 5.3 3.7 1.5 0.2刚毛49
50 5.0 3.3 1.4 0.2刚毛50
51 7.0 3.2 4.7 1.4彩色1
52 6.4 3.2 4.5 1.5彩色2
53 6.9 3.1 4.9 1.5彩色3
.. ... ... ... ... ...... ..
98 6.2.9 4.3 1.3花色48
99 5.1 2.5 3.0 1.1花色49
100 5.7 2.8 4.1 1.3彩色50
101 6.3.3 6.0 2.5弗吉尼亚州1
102 5.8 2.7 5.1 1.9弗吉尼亚州2
103 7.1 3.0 5.9 2.1弗吉尼亚州3
.. ... ... ... ... ...... ..
148 6.5 3.0 5.2 2.0弗吉尼亚州48
149 6.2 3.4 5.4 2.3弗吉尼亚州49
150 5.9 3.0 5.1 1.8弗吉尼亚州50
值得一提的是,ave
在这里给出的是浮点而不是int。或者,可以将df$val
更改为seq_len(nrow(df))
。我刚刚在这里遇到了这个问题:有趣的是,这个数据表解决方案似乎比使用frank
:库(microbenchmark)更快;微基准(a=DT[,(val,num=frank(val)),by=list(cat)],b=DT[,(val,id=seq_len(.N)),by=list(cat)],times=1000L)
谢谢!dplyr
解决方案很好。但是,如果像我一样,在尝试这种方法时不断出现奇怪的错误,请确保在plyr
和dplyr