如何在r中的一组观测值之间切换值

  • 本文关键字:一组 之间 r switch-statement
  • 更新时间 :
  • 英文 :


我有一个数据集,它有两个变量,一个字符和一个数字:

structure(list(ID = c("A", "B", "C", "D", "E", "A", "B", "C", 
"D", "E", "A", "B", "C", "D", "E", "A", "B", "C", "D", "E"), 
value = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
15, 16, 17, 18, 19, 20)), class = "data.frame", row.names = c(NA, 
-20L))

我想做的是切换";值";在每组";A";以及";E〃;对于每个序列的";A";以及";E";。

因此,我的最终输出应该是这样的:

ID   value
A      5
B      2
C      3
D      4
E      1
A      10
B      7 
C      8
D      9
E      6
A      15
B      12
C      13
D      14
E      11
A      20
B      17
C      18
D      19
E      16

我在这里使用了一个数字序列,只是为了简化示例,但我的实际值不是1到20的序列。因此,具有数字模式的解决方案在我的数据中不起作用。

谢谢!

在基本R中,您可以执行以下操作:

# matrix with indices of A's and E's in its two rows
ae <- matrix(which(df$ID %in% c('A', 'E')), nrow=2)
# switch A and E
df$value[ae] <- df$value[ae[2:1, ]]
df
#    ID value
# 1   A     5
# 2   B     2
# 3   C     3
# 4   D     4
# 5   E     1
# 6   A    10
# 7   B     7
# 8   C     8
# 9   D     9
# 10  E     6
# 11  A    15
# 12  B    12
# 13  C    13
# 14  D    14
# 15  E    11
# 16  A    20
# 17  B    17
# 18  C    18
# 19  D    19
# 20  E    16

以下是dplyrcase_when:的方法

library(dplyr)
df %>% 
group_by(gp = cumsum(ID == 'A')) %>% 
mutate(value = case_when(ID == "A" ~ value[ID == "E"],
ID == "E" ~ value[ID == "A"],
TRUE ~ value)) %>% 
ungroup() %>% 
select(-gp)

输出

# A tibble: 20 × 2
ID    value
<chr> <dbl>
1 A         5
2 B         2
3 C         3
4 D         4
5 E         1
6 A        10
7 B         7
8 C         8
9 D         9
10 E         6
11 A        15
12 B        12
13 C        13
14 D        14
15 E        11
16 A        20
17 B        17
18 C        18
19 D        19
20 E        16

也许只切换ID:更好

df$ID <- ifelse(df$ID == "A", "E", ifelse(df$ID == "E", "A", df$ID))

使用data.table,在"A";以及";E";,然后使用矢量化索引来更新value:

library(data.table)
setDT(df)[ID %chin% c("A", "E"), value := value[1:.N + c(1, -1)]][]
#>     ID value
#>  1:  A     5
#>  2:  B     2
#>  3:  C     3
#>  4:  D     4
#>  5:  E     1
#>  6:  A    10
#>  7:  B     7
#>  8:  C     8
#>  9:  D     9
#> 10:  E     6
#> 11:  A    15
#> 12:  B    12
#> 13:  C    13
#> 14:  D    14
#> 15:  E    11
#> 16:  A    20
#> 17:  B    17
#> 18:  C    18
#> 19:  D    19
#> 20:  E    16

可能使用较短的代码,但这里有一个建议

library(tidyverse)
df %>%  
pivot_wider(names_from = ID, 
values_from = value) %>% 
unnest(everything()) %>%  
transform(A = E, 
E = A) %>% 
pivot_longer(cols = everything())
# A tibble: 20 x 2
name  value
<chr> <dbl>
1 A         5
2 B         2
3 C         3
4 D         4
5 E         1
6 A        10
7 B         7
8 C         8
9 D         9
10 E         6
11 A        15
12 B        12
13 C        13
14 D        14
15 E        11
16 A        20
17 B        17
18 C        18
19 D        19
20 E        16

我只是简单地切换它们。看起来这可能更花哨,但我会保持简单。

vA <- df$value[df$ID == "A"]
vE <- df$value[df$ID == "E"]
df$value[df$ID == "A"] <- vE
df$value[df$ID == "E"] <- vA
df
#>    ID value
#> 1   A     5
#> 2   B     2
#> 3   C     3
#> 4   D     4
#> 5   E     1
#> 6   A    10
#> 7   B     7
#> 8   C     8
#> 9   D     9
#> 10  E     6
#> 11  A    15
#> 12  B    12
#> 13  C    13
#> 14  D    14
#> 15  E    11
#> 16  A    20
#> 17  B    17
#> 18  C    18
#> 19  D    19
#> 20  E    16

最新更新