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

时间:2018-06-14 08:16:07

标签: r dataframe tibble

给定如下数据框:

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。

我想根据标签和数字来分析timediff。 首先,我使用

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

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

请告知我怎样才能告诉&#34; combined_factor列级别是数字外观的顺序(9然后是4然后是6和0)?

我已经探讨了这个问题: Order factor levels according to the order in which the levels appear in the data

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

例如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"

1 个答案:

答案 0 :(得分:1)

由于您提供的数据重复性差,我将使用自己的数据:

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)tidyr&#39; s unite或2)interaction创建交互。另请参阅?sort"The sort order for factors is the order of their levels"。因此,您只需更改因子级别即可。