R dataframe crear nuevas columnas mulitple de las columnas existentes utilizando a través / all_of / mutate_if
Tengo un marco de datos (ejemplo abajo) que tiene respuestas a un cuestionario en varios días.
> df %>%
mutate (Sigma_Bucket_Q1 = if_else(Sigma_Q1 >= Median_Sigma_Q1,
"Above Median Volatility", "Below Median Volatility"))
# A tibble: 19 x 12
UserId Days_From_First_Use Q1 Q2 Q3 Sigma_Q1 Sigma_Q2 Sigma_Q3 Median_Sigma_Q1 Median_Sigma_Q2 Median_Sigma_Q3 Sigma_Bucket_Q1
1 A 0 3 2 1 1.10 0.837 0.548 1.45 1.59 1.53 Below Median Volatility
2 A 1 1 0 0 1.10 0.837 0.548 1.45 1.59 1.53 Below Median Volatility
3 A 2 1 1 0 1.10 0.837 0.548 1.45 1.59 1.53 Below Median Volatility
4 A 3 0 2 0 1.10 0.837 0.548 1.45 1.59 1.53 Below Median Volatility
5 A 4 1 1 1 1.10 0.837 0.548 1.45 1.59 1.53 Below Median Volatility
6 B 0 4 8 2 1.26 2.5 2.06 1.45 1.59 1.53 Below Median Volatility
7 B 2 2 2 1 1.26 2.5 2.06 1.45 1.59 1.53 Below Median Volatility
8 B 4 5 6 5 1.26 2.5 2.06 1.45 1.59 1.53 Below Median Volatility
9 B 5 4 5 5 1.26 2.5 2.06 1.45 1.59 1.53 Below Median Volatility
10 C 0 5 7 2 1.64 1.87 1 1.45 1.59 1.53 Above Median Volatility
11 C 1 2 2 2 1.64 1.87 1 1.45 1.59 1.53 Above Median Volatility
12 C 2 5 5 4 1.64 1.87 1 1.45 1.59 1.53 Above Median Volatility
13 C 3 6 5 3 1.64 1.87 1 1.45 1.59 1.53 Above Median Volatility
14 C 4 6 6 4 1.64 1.87 1 1.45 1.59 1.53 Above Median Volatility
15 D 0 5 3 5 2.35 1.30 2.30 1.45 1.59 1.53 Above Median Volatility
16 D 1 5 3 4 2.35 1.30 2.30 1.45 1.59 1.53 Above Median Volatility
17 D 2 4 2 6 2.35 1.30 2.30 1.45 1.59 1.53 Above Median Volatility
18 D 3 0 0 1 2.35 1.30 2.30 1.45 1.59 1.53 Above Median Volatility
19 D 4 1 1 1 2.35 1.30 2.30 1.45 1.59 1.53 Above Median Volatility
Columnas Q1
, Q2
y Q3
tener las respuestas, mientras Sigma_Q1
, Sigma_Q2
y Sigma Q3
tener la serie de tiempo desviaciones estándar de las respuestas de cada sujeto a cada pregunta. Median_Sigma_1
, Median_Sigma_2
, y Median_Sigma_3
tener la mediana desviación estándar entre sujetos para sus respuestas a Q1
, Q2
y Q3
. Quiero clasificar a cada sujeto como un sujeto de volatilidad mediana superior o inferior según sea o no Sigma_Q1 > Median_Sigma_Q1
y así sucesivamente. Mi expresión para generar Sigma_Bucket_Q1
funciona bien; es visible justo antes de la tibble.
Pero cuando intento generalizarlo para generar todos los Sigma_Buckets simultáneamente (mi verdadero problema tiene 21 nombres), me encuentro con un problema. Lo intenté:
df %>%
mutate (across(all_of(paste0("Sigma_Bucket_", c("Q1", "Q2", "Q3")) = if_else(paste0("Sigma_", {.col}) >= paste0("Median_Sigma_", {.col}),
"Above Median Volatility", "Below Median Volatility")))
Recibo un mensaje de error críptico y no puedo determinar lo que necesito arreglar:
> df %>%
+ mutate (across(all_of(paste0("Sigma_Bucket_", c("Q1", "Q2", "Q3")) = if_else(paste0("Sigma_", {.col}) >= paste0("Median_Sigma_", {.col}),
Error: unexpected '=' in:
"df %>%
mutate (across(all_of(paste0("Sigma_Bucket_", c("Q1", "Q2", "Q3")) ="
> "Above Median Volatility", "Below Median Volatility")))
Error: unexpected ',' in " "Above Median Volatility","
¿Cómo puedo modificar mi declaración para hacer las 3 columnas (las 21 en el problema real) sin escribir una línea para cada pregunta?
Mirando a través de varias respuestas en StackOverflow sugiere que mutate_if
podría ser la base de una solución, pero no veo cómo se puede utilizar en este entorno particular.
Muchas gracias por adelantado por su ayuda
Thomas Philips
Pregunta hecha hace 3 años, 4 meses, 26 días - Por codervoyager
4 Respuestas:
-
Aquí hay una solución usando
map
:map2_df( df %>% select(starts_with("Sigma_Q")), df %>% select(starts_with("Median_Sigma_Q")), ~if_else(.x >= .y, "Above Median Volatility", "Below Median Volatility")) %>% rename_with(~str_replace(.x, "Sigma", "Sigma_Bucket"))
Producto:
# A tibble: 19 x 3 Sigma_Bucket_Q1 Sigma_Bucket_Q2 Sigma_Bucket_Q3
1 Below Median Volatility Below Median Volatility Below Median Volatility 2 Below Median Volatility Below Median Volatility Below Median Volatility 3 Below Median Volatility Below Median Volatility Below Median Volatility 4 Below Median Volatility Below Median Volatility Below Median Volatility 5 Below Median Volatility Below Median Volatility Below Median Volatility 6 Below Median Volatility Above Median Volatility Above Median Volatility 7 Below Median Volatility Above Median Volatility Above Median Volatility 8 Below Median Volatility Above Median Volatility Above Median Volatility 9 Below Median Volatility Above Median Volatility Above Median Volatility 10 Above Median Volatility Above Median Volatility Below Median Volatility 11 Above Median Volatility Above Median Volatility Below Median Volatility 12 Above Median Volatility Above Median Volatility Below Median Volatility 13 Above Median Volatility Above Median Volatility Below Median Volatility 14 Above Median Volatility Above Median Volatility Below Median Volatility 15 Above Median Volatility Below Median Volatility Above Median Volatility 16 Above Median Volatility Below Median Volatility Above Median Volatility 17 Above Median Volatility Below Median Volatility Above Median Volatility 18 Above Median Volatility Below Median Volatility Above Median Volatility 19 Above Median Volatility Below Median Volatility Above Median Volatility Respondida el Dec 21, 2020 a las 03:26 - por devdynamox
Votos positivos: 0 | Votos negativos: 0 -
across
no tienen acceso a los nombres de las columnas, sólo pasan los valores de la columna. Puedes probar este enfoque de base R vectorizado sin bucles.col1 <- grep('^Sigma_Q\\d$', names(df), value = TRUE) col2 <- grep('^Median_Sigma_Q\\d$', names(df), value = TRUE) df[paste0(col1, '_Bucket')] <- c("Below Median Volatility", "Above Median Volatility")[(df[col1] >= df[col2]) + 1]
Respondida el Dec 21, 2020 a las 03:33 - por binarybrainiac
Votos positivos: 0 | Votos negativos: 0 -
Parece que hay un pequeño error en la forma en que estás intentando utilizar la función
across
en combinación conall_of
para generar las nuevas columnas"Sigma_Bucket_Q1"
,"Sigma_Bucket_Q2"
y"Sigma_Bucket_Q3"
.Aquí te dejo una forma de hacerlo utilizando la función
across
yall_of
, así comoif_else
para generar las nuevas columnas de forma simultánea:R df %>% mutate( across(all_of(paste0("Sigma_", c("Q1", "Q2", "Q3"))), ~ if_else(. >= get(paste0("Median_Sigma_", sub("Sigma_", "", cur_column()))), "Above Median Volatility", "Below Median Volatility"), .names = "Sigma_Bucket_{.col}") )
Lo que hemos hecho aquí es utilizar
across
para aplicar la condición deif_else
a las columnas seleccionadas, usandoget
para obtener el valor de la columnaMedian_Sigma
correspondiente. La opción.names
nos permite especificar el nombre de las nuevas columnas generadas.Espero que esta solución te sea de ayuda. ¡Déjame saber si tienes alguna otra pregunta!
Respondida el Dec 22, 2020 a las 03:26 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Para crear varias columnas nuevas en un marco de datos R utilizando
across()
yif_else()
para una lista de variables especificada, puedes utilizar el siguiente código:r df %>% mutate(across(all_of(c("Sigma_Q1", "Sigma_Q2", "Sigma_Q3")), ~ if_else(. >= get(paste0("Median_Sigma_", .)), "Above Median Volatility", "Below Median Volatility")))
En este código:
across(all_of(c("Sigma_Q1", "Sigma_Q2", "Sigma_Q3")))
selecciona todas las columnas especificadas en la listac("Sigma_Q1", "Sigma_Q2", "Sigma_Q3")
.~ if_else(. >= get(paste0("Median_Sigma_", .)), "Above Median Volatility", "Below Median Volatility")
es una función anónima que aplica la condiciónif_else()
a cada una de las columnas seleccionadas..
representa el valor actual de la columna.get(paste0("Median_Sigma_", .))
recupera el valor de la columnaMedian_Sigma_
correspondiente a la columna actual.if_else(. >= get(paste0("Median_Sigma_", .)), "Above Median Volatility", "Below Median Volatility")
comprueba si el valor de la columna actual es mayor o igual que el valor de la columnaMedian_Sigma_
correspondiente y devuelve "Above Median Volatility" o "Below Median Volatility" en consecuencia.
df
:Sigma_Bucket_Q1
,Sigma_Bucket_Q2
ySigma_Bucket_Q3
, que clasifican a cada sujeto como "Above Median Volatility" o "Below Median Volatility" según sus valores de desviación estándar para las preguntas Q1, Q2 y Q3, respectivamente.Respondida el Dec 22, 2020 a las 03:32 - por Gemini
Votos positivos: 0 | Votos negativos: 0