如何根据另一列中值的出现设置因子水平顺序?

How to set factor levels order according to appearance of values in another column?

给定如下数据框:

label digit timediff
1         9        0        
1         9        9        
1         9       17        
2         9       17        
2         9        8        
1         9        8        
2         4      200        
1         4       17        
2         4       17        
2         4        8

我正在尝试处理连续数字(这是 PIN 码分析)。 我的密码是 9460。

我想根据label和digit来分析timediff。 首先,我使用

创建了一个列
df$combined_factor <- with(df, interaction(label, digit))

但现在我需要根据数字外观来调整因子水平。

请指教如何才能"tell" combined_factor 列级别按数字出现的顺序排列(9 然后 4 然后 6 和 0)?

我探讨了这个问题:

但在我的情况下,我有标签。

例如combined_factor可以是: 1.9 2.4 ...

我希望它按数字顺序排列:1.9, ... 1.4, ... 1.6 ... 1.0, ... 2.9, ... 2.4, ... 2.6, ... 2.0 ....

label_digit    timediff
   <fct>          <dbl>
 1 1.9                0
 2 1.9                9
 3 1.9               17
 4 1.9               17
 5 1.9                8
 6 1.9                8
 7 1.4              200
 8 1.4               17
 9 1.4               17
10 1.4                8

levels(df$label_digit)
[1] "1.0" "2.0" "1.4" "2.4" "1.6" "2.6" "1.9" "2.9"

预计:

levels(df$label_digit):
[1] "1.9" "1.4" "1.6" "1.0" "2.9" "2.4" "2.6" "2.0"

由于您提供的可重现数据不佳,我将使用自己的数据:

d <- structure(list(label = c(1L, 1L, 1L, 2L, 2L, 1L, 2L, 1L, 2L, 
2L), digit = c(9L, 9L, 6L, 9L, 9L, 0L, 4L, 4L, 4L, 4L), timediff = c(0L, 
9L, 17L, 17L, 8L, 8L, 200L, 17L, 17L, 8L)), .Names = c("label", 
"digit", "timediff"), class = "data.frame", row.names = c(NA, 
-10L))

那你可以试试tidyverse

d %>% 
  mutate(digit=factor(digit, levels = c(9,4,6,0))) %>% 
  arrange(label, digit) 
   label digit timediff
1      1     9        0
2      1     9        9
3      1     4       17
4      1     6       17
5      1     0        8
6      2     9       17
7      2     9        8
8      2     4      200
9      2     4       17
10     2     4        8

然后交互使用:

d %>% 
  mutate(digit=factor(digit, levels = c(9,4,6,0))) %>% 
  arrange(label, digit) %>% 
  unite(ID, label, digit, sep=".") %>% 
  mutate(ID=factor(ID, levels = unique(ID))) %>% 
  with(.,levels(ID))
[1] "1.9" "1.4" "1.6" "1.0" "2.9" "2.4"

或者在基础 R 中简单地使用 order

d[order(d$label, factor(d$digit,levels = c(9,4,6,0))),]
   label digit timediff
1      1     9        0
2      1     9        9
8      1     4       17
3      1     6       17
6      1     0        8
4      2     9       17
5      2     9        8
7      2     4      200
9      2     4       17
10     2     4        8

然后

d1 <- d[order(d$label, factor(d$digit,levels = c(9,4,6,0))),]
d1$combined_factor <- with(d1, interaction(label, digit))
d1$combined_factor <- factor(d1$combined_factor, levels = unique(d1$combined_factor))
levels(d1$combined_factor)
[1] "1.9" "1.4" "1.6" "1.0" "2.9" "2.4"

作为你的功能你可以试试

foo <- function(df, Code) df[order(df$label, factor(df$digit, levels = Code)),]
foo(d, c(9,4,6,0))

不需要使用 interaction 部分。如果你需要它。之后使用 1) tidyrunite 或 2) interaction 创建交互。另见 ?sort"The sort order for factors is the order of their levels"。因此,您只需更改因子水平。