r语言 - 用数字组合相似的字符串,并保持首次出现的顺序



我有一个看起来像这个例子的数据帧(只是大得多):

var <- c('Peter','Ben','Mary','Peter.1','Ben.1','Mary.1','Peter.2','Ben.2','Mary.2')
v1 <- c(0.4, 0.6, 0.7, 0.3, 0.9, 0.2, 0.4, 0.6, 0.7)
v2 <- c(0.5, 0.4, 0.2, 0.5, 0.4, 0.2, 0.1, 0.4, 0.2)
df <- data.frame(var, v1, v2)
var  v1  v2
1   Peter 0.4 0.5
2     Ben 0.6 0.4
3    Mary 0.7 0.2
4 Peter.1 0.3 0.5
5   Ben.1 0.9 0.4
6  Mary.1 0.2 0.2
7 Peter.2 0.4 0.1
8   Ben.2 0.6 0.4
9  Mary.2 0.7 0.2

我想根据没有后缀的名称对"var"中的字符串进行分组,并保持首次出现的原始顺序。期望输出:

var  v1  v2
1 Peter   0.4 0.5 # Peter appears first in the original data
2 Peter.1 0.3 0.5
3 Peter.2 0.4 0.1
4     Ben 0.6 0.4 # Ben appears second in the original data
5   Ben.1 0.9 0.4
6   Ben.2 0.6 0.4
7    Mary 0.7 0.2 # Mary appears third in the original data
8  Mary.1 0.2 0.2
9  Mary.2 0.7 0.2

我怎样才能做到这一点?

谢谢!

一个选项是创建一个临时列,不带.和数字(\d+)在末尾加上str_remove,然后使用factor指定为uniquelevels或使用matcharrange数据

library(dplyr)
library(stringr)
df <- df %>%
mutate(var1 = str_remove(var, "\.\d+$")) %>% 
arrange(factor(var1, levels = unique(var1))) %>%
select(-var1)

或者使用forcats中的fct_inorder,它将按首次出现的顺序转换为带有levelsfactor

library(forcats)
df %>% 
arrange(fct_inorder(str_remove(var, "\.\d+$")))

-输出

var  v1  v2
1   Peter 0.4 0.5
2 Peter.1 0.3 0.5
3 Peter.2 0.4 0.1
4     Ben 0.6 0.4
5   Ben.1 0.9 0.4
6   Ben.2 0.6 0.4
7    Mary 0.7 0.2
8  Mary.1 0.2 0.2
9  Mary.2 0.7 0.2

带有subdata.table::chgroup的紧凑选项

df[chgroup(sub("\..", "", df$var)),]
var  v1  v2
1   Peter 0.4 0.5
4 Peter.1 0.3 0.5
7 Peter.2 0.4 0.1
2     Ben 0.6 0.4
5   Ben.1 0.9 0.4
8   Ben.2 0.6 0.4
3    Mary 0.7 0.2
6  Mary.1 0.2 0.2
9  Mary.2 0.7 0.2

chgroup

重复的值组合在一起,但保留组顺序(根据每个组的第一次出现顺序),有效地

如果您不介意var中的值按字母顺序排序,那么最简单的解决方案是这样的:

df %>%
arrange(var)
var  v1  v2
1     Ben 0.6 0.4
2   Ben.1 0.9 0.4
3   Ben.2 0.6 0.4
4    Mary 0.7 0.2
5  Mary.1 0.2 0.2
6  Mary.2 0.7 0.2
7   Peter 0.4 0.5
8 Peter.1 0.3 0.5
9 Peter.2 0.4 0.1

separatevar列分成两列,将生成的 NA 替换为 0,排序并删除多余的列。

这适用于数字的数值而不是字符表示形式,例如,10 不会在 2 之前出现。 此外,arrange中的match可确保订单基于第一个出现顺序。

df %>%
separate(var, c("alpha", "no"), convert=TRUE, remove=FALSE, fill="right") %>% 
mutate(no = replace_na(no, 0)) %>%
arrange(match(alpha, alpha), no) %>%
select(-alpha, -no)

var  v1  v2
1   Peter 0.4 0.5
2 Peter.1 0.3 0.5
3 Peter.2 0.4 0.1
4     Ben 0.6 0.4
5   Ben.1 0.9 0.4
6   Ben.2 0.6 0.4
7    Mary 0.7 0.2
8  Mary.1 0.2 0.2
9  Mary.2 0.7 0.2

更新

在阅读问题的更新后,删除了以前的第一个解决方案。

最新更新