这在基础R中必须很简单,但它让我对dplyr发疯(总的来说,它让我的生活变得更好! 假设您有以下提示
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
df1 <- tibble(x=seq(5)*19, a1=seq(5)*1, a2=seq(5)*2, a3=seq(5)*4)
df1
#> # A tibble: 5 x 4
#> x a1 a2 a3
#> <dbl> <dbl> <dbl> <dbl>
#> 1 19 1 2 4
#> 2 38 2 4 8
#> 3 57 3 6 12
#> 4 76 4 8 16
#> 5 95 5 10 20
df2 <- tibble(b1=3, b2=0.5, b3=10)
df2
#> # A tibble: 1 x 3
#> b1 b2 b3
#> <dbl> <dbl> <dbl>
#> 1 3 0.5 10
创建于 2020-06-11 由 reprex 软件包 (v0.3.0(
然后我只想将 df1 a1 替换为 a1/b1,将 a2 替换为 a2/b2,依此类推。 这必须足够通用,以便在我有很多列时处理这种情况。 任何建议不胜感激。
您可以使用Map
df1[-1] <- Map(`/`, df1[-1], df2)
# A tibble: 5 x 4
# x a1 a2 a3
# <dbl> <dbl> <dbl> <dbl>
#1 19 0.333 4 0.4
#2 38 0.667 8 0.8
#3 57 1 12 1.2
#4 76 1.33 16 1.6
#5 95 1.67 20 2
或者,如果您想要一个tidyverse
解决方案,您可以在purrr
中使用map2
:
df1[-1] <- purrr::map2(df1[-1], df2, `/`)
您可以将rowwise()
与c_across()
一起使用
df1 %>%
rowwise() %>%
mutate(c_across(a1:a3) / df2, .keep = "unused") %>%
ungroup()
# # A tibble: 5 x 4
# x b1 b2 b3
# <dbl> <dbl> <dbl> <dbl>
# 1 19 0.333 4 0.4
# 2 38 0.667 8 0.8
# 3 57 1 12 1.2
# 4 76 1.33 16 1.6
# 5 95 1.67 20 2
另一个基本 R 选项
df1[-1] <- t(t(df1[-1]) / unlist(df2))
df1
# # A tibble: 5 x 4
# x a1 a2 a3
# <dbl> <dbl> <dbl> <dbl>
# 1 19 0.333 4 0.4
# 2 38 0.667 8 0.8
# 3 57 1 12 1.2
# 4 76 1.33 16 1.6
# 5 95 1.67 20 2
一种解决方案可能是:
bind_cols(select(df1, x),
sweep(select(df1, -x), 2, FUN = `/`, unlist(df2)))
x a1 a2 a3
<dbl> <dbl> <dbl> <dbl>
1 19 0.333 4 0.4
2 38 0.667 8 0.8
3 57 1 12 1.2
4 76 1.33 16 1.6
5 95 1.67 20 2
或者像这样,如果你有更多的列:
df1[,2:4] <- df1[,2:4] / df2 %>% slice(rep(1:n(), each = nrow(df1)))
# A tibble: 5 x 4
x a1 a2 a3
<dbl> <dbl> <dbl> <dbl>
1 19 0.111 8 0.04
2 38 0.222 16 0.08
3 57 0.333 24 0.12
4 76 0.444 32 0.16
5 95 0.556 40 0.2
另一个选项,它考虑变量的列名,并将它们与必须除以的数字配对。cur_column()
在mutate(across())
中派上用场的功能 - 您要使用的功能
# vector of divisors
l <- as.list(as.numeric(df2[1,]))
df1 %>%
mutate(across(starts_with("a"),
~ ./l[[na.omit(as.numeric(unlist(strsplit(cur_column(), "[^[:digit:]]"))))]]))
输出
# A tibble: 5 x 4
# x a1 a2 a3
# <dbl> <dbl> <dbl> <dbl>
# 1 19 0.333 4 0.4
# 2 38 0.667 8 0.8
# 3 57 1 12 1.2
# 4 76 1.33 16 1.6
# 5 95 1.67 20 2
一个带有base R
的选项
df1[-1] <- df1[-1]/unlist(df2)[col(df1)]