Tenho uma longa lista de variáveis que desejo multiplicar pelas variáveis correspondentes e somar. a_1
corresponde a b_1
, a_2
a b_2
etc. A saída desejada seria calculada por(a_1*b_1 + a_2*b_2...)
library(dplyr)
(df <- tibble(
a_1 = sample(1:5),
a_2 = sample(1:5),
b_1 = sample(1:5),
b_2 = sample(1:5),
desired_output = (a_1*b_1 + a_2*b_2)
))
# A tibble: 5 × 5
a_1 a_2 b_1 b_2 desired_output
<int> <int> <int> <int> <int>
1 4 5 1 3 19
2 1 2 2 5 12
3 2 1 4 2 10
4 5 3 5 1 28
5 3 4 3 4 25
Eu tentei e falhei em escrever uma função para fazer isso (sou muito novo em tentar escrever funções!) por exemplo
df %>%
mutate(desired_output = function(df) {
for (i in 1:2) {
y1 <- get(paste0(x,'$','a_',i))
y2 <- get(paste0(x,'$','a_',i))
z <- y1*y2
}
return(z)
}
Das soluções aqui, eu provavelmente usaria (1), (2b) ou (5), dependendo de quais pacotes você prefere usar (dplyr, base, dplyr/dplyover, respectivamente).
1) escolha várias
pick(...)
chamadas e userowSums
como mostrado:dando
2) transformar Uma tradução razoavelmente direta disso para a base R resulta em:
2a) Esta versão de (2) é ainda mais compacta, embora (2) pareça mais clara:
2b) (2) não é amigável ao pipe base, pois usa
df
vários tempos. Se usado dentro de um pipe, faça assim (ou use uma função anônima, embora isso tenda a ser difícil de ler devido a todos os parênteses na sintaxe, razão pela qual preferimos o código aqui):3) mutate/get Uma abordagem razoavelmente próxima da tentativa na questão é
4) transformar/obter ou traduzir (3) para a base R:
5) dplyover O pacote dplyover no github tem um
across2
que é semelhanteacross
, mas manipula dois conjuntos de colunas ao mesmo tempo.6) reduce2
reduce2
no pacote purrr pode manipular dois conjuntos de colunas de uma vez, embora comparado aoacross2
seu uso seja um pouco mais complicado. Em troca, envolve apenas pacotes do CRAN.Observação
Devido ao uso de números aleatórios na questão, a entrada não é reproduzível. Da próxima vez, use
set.seed(...)
primeiro.Estes são os dados que foram usados na questão mostrados de forma reproduzível:
No R básico, para uma solução geral, você pode primeiro identificar as colunas que deseja pelo padrão (aqui, as colunas de interesse (
ccols
) são identificadas por uma letra, sublinhado e número - por exemplo, "\\D_\\d") e, em seguida, usarsapply
withinrowSums
para realizar a multiplicação e a adição:Note que se você tivesse certeza de que eram simplesmente "a_xx" e "b_xx", você poderia simplesmente fazer:
Dados (com semente)
Aqui está uma opção base R com
split.default
+rowSums
o que dá
Dados
Uma opção poderia ser:
Acho muito mais intuitivo nessas situações colocar os dados em formato longo. Como você marcou tidyverse, isso significa:
tidyr::pivot_longer()
, um rápidomutate()
para criar o resultado, entãopivot_wider()
.:É verdade que isso envolve mais linhas de código do que outras abordagens, mas a) o cálculo em si
result = sum(a * b)
é muito mais fácil de entender nesse formato (para mim, pelo menos) e b) geralmente faz mais sentido pularpivot_wider()
e manter os dados em formato longo para as próximas etapas da manipulação de dados, caso em que isso se torna muito mais curto.