我所拥有的是一个数据集“df”,它在组内有子组,除了子组普遍编号为1-N,而不是每组中的1-n。目前它看起来像这样:
df = data.frame( c( rep(58, 10), rep(59, 12) ),
c( rep(417, 4), rep(418, 5), rep(419, 1), rep(420, 7),
rep(421, 5) ) )
colnames(df) = c("group", "subgroup_global")
df
group subgroup_global
1 58 417
2 58 417
3 58 417
4 58 417
5 58 418
6 58 418
7 58 418
8 58 418
9 58 418
10 58 419
11 59 420
12 59 420
13 59 420
14 59 420
15 59 420
16 59 420
17 59 420
18 59 421
19 59 421
20 59 421
21 59 421
22 59 421
我想把它变成这个,所以每个组中的第一个子组重新开始为1:
group subgroup_global subgroup
1 58 417 1
2 58 417 1
3 58 417 1
4 58 417 1
5 58 418 2
6 58 418 2
7 58 418 2
8 58 418 2
9 58 418 2
10 58 419 3
11 59 420 1
12 59 420 1
13 59 420 1
14 59 420 1
15 59 420 1
16 59 420 1
17 59 420 1
18 59 421 2
19 59 421 2
20 59 421 2
21 59 421 2
22 59 421 2
我已经找到了一个非常麻烦的方法,基本上有两个嵌套循环:
renumber <- function(c) {
c$subgroup <- 1
x <- which(!duplicated(c$subgroup_global))
c[x, "subgroup"] <- 1:length(x)
for(i in x) {
val = c[i, "subgroup"]
valGlobal = c[i, "subgroup_global"]
rows = which(c$subgroup_global == as.numeric(valGlobal))
c[rows, "subgroup"] = val
}
c
}
接下来,我在数据集的每个组中迭代这个“重新编号”函数(你会注意到我潜入了基础R中的“过滤器”dplyr函数):
df_renumbered <- data.frame()
for(i in unique(df$group)) {
df_partial <- filter(df, group == i)
df_partial <- renumber(df_partial)
df_renumbered <- rbind(df_renumbered, df_partial)
}
df_renumbered
除了效率低下之外,这段代码(在所有意图和目的上)花费了无限的时间在我的真实数据集上运行,其中包含200,000多行,3,000多个组和27,000多个子组。您能否使用dplyr或base R或两者的某些组合提供可行的解决方案?
答案 0 :(得分:1)
您可以使用base
函数ave
:
ave(df$subgroup_global,df$group,FUN=function(x) as.numeric(factor(x)))
答案 1 :(得分:0)
我更喜欢data.table
library(data.table)
setDT(df)
setkey(df, group, subgroup_global)
df[, subgroup:=as.factor(subgroup_global), by=group] # or
df[, subgroup:=as.numeric(as.factor(subgroup_global)), by=group]
# from data.table 1.9.6 on:
setDT(df)[, subgroup := frank(subgroup_global, ties.method = "dense"), by=group]
# (in this case setkey() above is not necessary)
答案 2 :(得分:0)
编辑:如果as.numeric(as.factor(x))不起作用(无论出于何种原因我还没弄明白),请使用以下函数对值进行重新编号。
# Create your data
df = data.frame( c( rep(58, 10), rep(59, 12) ),
c( rep(417, 4), rep(418, 5), rep(419, 1), rep(420, 7),
rep(421, 5) ) )
colnames(df) = c("group", "subgroup_global")
# Define function to replace values.
replace.values <- function(search, replace, x){
return(replace[ match(x, search) ])
}
# Use by... to loop through all groups in the data.frame
# See how function inside by() works by setting: x <- df[df[,"group"]==df[1,"group"],]
df <- do.call("rbind", by(df, df[,"group"], function(x){
# replace unique(subgroup_global) by values in the range 1:length(unique(subgroup_global))
ux <- unique(x[,"subgroup_global"])
return(cbind(x, subgroup=replace.values(ux, 1:length(ux), x[,"subgroup_global"])))
}))
rownames(df) <- NULL
# Print you new df
print(df)
group subgroup_global subgroup
1 58 417 1
2 58 417 1
3 58 417 1
4 58 417 1
5 58 418 2
6 58 418 2
7 58 418 2
8 58 418 2
9 58 418 2
10 58 419 3
11 59 420 1
12 59 420 1
13 59 420 1
14 59 420 1
15 59 420 1
16 59 420 1
17 59 420 1
18 59 421 2
19 59 421 2
20 59 421 2
21 59 421 2
22 59 421 2
老人回答:我知道很久以前就问过这个问题了。在过去,我还使用as.numeric(factor(x))来解决问题。但是,目前(2016.12.21)它不再适用于我的R版本(3.3.1)。
新方法是用1:length(unique(subgroup_global))范围内的值替换unique(subgroup_global)。我在下面解决了你的问题。
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg);}
100% { -webkit-transform: rotate(360deg);}
}
@-moz-keyframes spin {
0% { -moz-transform: rotate(0deg);}
100% { -moz-transform: rotate(360deg);}
}
@-o-keyframes spin {
0% { -o-transform: rotate(0deg);}
100% { -o-transform: rotate(360deg);}
}
@-ms-keyframes spin {
0% { -ms-transform: rotate(0deg);}
100% { -ms-transform: rotate(360deg);}
}
@-keyframes spin {
0% { transform: rotate(0deg);}
100% { transform: rotate(360deg);}
}
header .spinner {
position: absolute;
width: 100%;
text-align: center;
margin: 0 auto;
left: 0;
-webkit-animation:spin 1s ease-out .5s;
-moz-animation:spin 1s ease-out .5s;
animation:spin 1s ease-out .5s;
transform-origin: 50%;
}