首先,感谢所有为本网站做出贡献的人。它对我弄清楚 R 很有帮助。
我有一个结构如下的数据集(非常过于简单的示例):
#> Var 1 Var2 Var 3 Var 4 Var5
#> 1 1 1 A 1200
#> 2 1 2 A 2300
#> 3 1 1 A 1200
#> 4 2 2 A 2300
#> 5 2 1 B 1200
#> 6 3 2 B 2300
#> 7 3 1 B 1200
#> 8 3 2 B 2300
#> 9 3 1 B 1200
#> 10 4 2 B 2300
我想 (1) 根据 Var 1、Var 2 和 Var 3 将数据分组在一起;这往往会创建两行组。在这些配对中,我希望 (2) 根据配对中其他观测值的 Var 4 和 Var 5 的值创建一个新变量 (Var 6)。在步骤 (2) 中,我基本上想创建一个变量来交换每对 Var 5 的观察结果。
代码如下所示:
df2 <- df1 %>%
dplyr::group_by(Var1, Var2, Var3) %>%
dplyr::mutate(Var6 = case_when(Var5 == A ~ Var5[Var5 == B]), Var5 == B ~ Var5[Var5 == A])
)
Output should look like this:
#> Var 1 Var2 Var 3 Var 4 Var5 Var 6
#> 1 1 1 A 1200 2300
#> 2 1 2 A 2300 1200
#> 3 1 1 A 1200 2300
#> 4 2 2 A 2300 1200
#> 5 2 1 B 1200 2300
#> 6 3 2 B 2300 1200
#> 7 3 1 B 1200 2300
#> 8 3 2 B 2300 1200
#> 9 3 1 B 1200 2300
#> 10 4 2 B 2300 1200
使用上面的代码,我收到以下错误消息:
`Var 6` must be size 1, not 0.
Backtrace:
1. ... %>% ...
9. dplyr:::dplyr_internal_error(...)
我要更改
Var1
,然后仅对其进行分组,这样我们就可以获得 2 行的组。我还将确保我们有几个仅包含 1 行的组,用于演示值交换逻辑。您不需要第一个 mutate
与您的真实数据,我们假设它有足够的可变性来为您提供您所说的期望的 2 行。
df1 %>%
mutate(Var1 = replace(rep(1:5, each=2), 10, 6)) %>%
group_by(Var1) %>%
mutate(Var6 = if (n() == 1) Var5 else rev(Var5)) %>%
ungroup()
# # A tibble: 10 × 6
# Var1 Var2 Var3 Var4 Var5 Var6
# <dbl> <int> <int> <chr> <int> <int>
# 1 1 1 1 A 1200 2300
# 2 1 1 2 A 2300 1200
# 3 2 1 1 A 1200 2300
# 4 2 2 2 A 2300 1200
# 5 3 2 1 B 1200 2300
# 6 3 3 2 B 2300 1200
# 7 4 3 1 B 1200 2300
# 8 4 3 2 B 2300 1200
# 9 5 3 1 B 1200 1200
# 10 6 4 2 B 2300 2300
这确实依赖于它们仅由 1 或 2 行组成,绝不会更多。如果这是一个因素,那么
rev(.)
黑客攻击很可能会失败。如果是这样的话,那么我们需要在有多行时想出逻辑。
为此,我们可以生成一个简单的函数,一旦“这一行”的值被删除,该函数就会获取第一个值。事实上,我会给你两个选择:
Var5[-i][1]
)确保删除该行的值,并获取第一个剩余值;如果由于某种原因你在一个组中重复Var5
,那么这可能会导致相同的值setdiff
,从候选中删除该行的值并返回第一个剩余值;如果你在一个组中有重复Var5
,这个方法保证你不会得到相同的值对于这两者中的每一个,我还使用
coalesce
提供清理操作,以防您 must 在 Var6
中具有值,默认为原始 Var5
。当组只有 1 行或 Var5
不变时,这非常有用。
df1 %>%
mutate(Var1 = replace(rep(1:5, each=2), 10, 6)) %>%
group_by(Var1) %>%
mutate(
Var6a = sapply(row_number(), function(i) Var5[-i][1]),
Var6b = coalesce(Var6a, Var5),
Var6c = sapply(Var5, function(v5) setdiff(Var5, v5)[1]),
Var6d = coalesce(Var6c, Var5)
) %>%
ungroup()
# # A tibble: 10 × 9
# Var1 Var2 Var3 Var4 Var5 Var6a Var6b Var6c Var6d
# <dbl> <int> <int> <chr> <int> <int> <int> <int> <int>
# 1 1 1 1 A 1200 2300 2300 2300 2300
# 2 1 1 2 A 2300 1200 1200 1200 1200
# 3 2 1 1 A 1200 2300 2300 2300 2300
# 4 2 2 2 A 2300 1200 1200 1200 1200
# 5 3 2 1 B 1200 2300 2300 2300 2300
# 6 3 3 2 B 2300 1200 1200 1200 1200
# 7 4 3 1 B 1200 2300 2300 2300 2300
# 8 4 3 2 B 2300 1200 1200 1200 1200
# 9 5 3 1 B 1200 NA 1200 NA 1200
# 10 6 4 2 B 2300 NA 2300 NA 2300