如何在R中交换一组观测值的值

3

我有一个数据集,其中包含两个变量,一个是字符型,一个是数值型:

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"序列之间交换"value"变量的值。因此,我的最终输出应该如下所示:
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的序列。因此,在我的数据中,具有数字模式的解决方案将无法奏效。
谢谢!
6个回答

1
也许更好的方法是直接切换ID:
df$ID <- ifelse(df$ID == "A", "E", ifelse(df$ID == "E", "A", df$ID))

1
使用 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

1
在基础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

1
这里有一个使用 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

0

可能有更短的代码实现方式,但这里提供一个建议

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

0

我只是简单地交换它们。这似乎可以更加花哨,但我会保持简单。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接