Supongamos que tengo un marco de datos con la siguiente estructura:

|id  | segment1 | segment 2|
|----|----------|----------|
|1   | 1        |  0       |   
|2   | 1        |  0       |
|3   | 0        |  1       |
|4   | 1        |  0       |
|5   | 0        |  1       |

¿Cómo pivoto los datos de modo que, en lugar de tener las 2 columnas de "segmento", solo tengo 1 columna que dice "segmento1" o "segmento2"? Estaba pensando en pivot_longer pero no creo que estemos creando el marco de datos por más tiempo. Parece que definitivamente hay una forma más rápida que usar mutate con un if_else o crear una nueva columna y asignar manualmente los valores.

Nota: Sin embargo, esta transformación no debería generar un marco de datos más largo, ya que solo estamos contrayendo columnas

2
Sebastian Rivas 12 may. 2020 a las 00:51

4 respuestas

Podemos usar max.col de base R para obtener el índice del valor máximo por cada fila de la segunda y tercera columna, use ese índice para obtener los nombres de columna correspondientes de los datos

cbind(df1[1], segment = names(df1)[-1][max.col(df1[-1], 'first')])
#  id  segment
#1  1 segment1
#2  2 segment1
#3  3 segment2
#4  4 segment1
#5  5 segment2

O usando tidyverse

library(dplyr)
library(tidyr)
df1 %>%
      pivot_longer(cols = -id, names_to = 'segment') %>%
      filter(as.logical(value)) %>%
      select(-value)
# A tibble: 5 x 2
#     id segment 
#  <int> <chr>   
#1     1 segment1
#2     2 segment1
#3     3 segment2
#4     4 segment1
#5     5 segment2

Datos

df1 <- structure(list(id = 1:5, segment1 = c(1, 1, 0, 1, 0), segment2 = c(0, 
0, 1, 0, 1)), class = "data.frame", row.names = c(NA, -5L))
4
akrun 11 may. 2020 a las 21:59
      A = data.frame(id = c(1, 2, 3), 
                     segment1 = c(1, 1, 0), 
                     segment2 = c(0, 0, 1))

tidyr::pivot_longer(A, c(segment1, segment2)) %>% 
                           filter(value == 1) %>% 
                            select(-value)
# A tibble: 3 x 2
     id name    
  <dbl> <chr>   
1     1 segment1
2     2 segment1
3     3 segment2
2
Taufi 11 may. 2020 a las 21:56

Así es como haría esto, desea pivot_longer y luego soltar los valores 0, creo.

library(tidyr)
df <- data.frame(id = c(1, 2, 3, 4, 5),
                 segment1 = c(1, 1, 0, 1, 0),
                 segment2 = c(0, 0, 1, 0, 1))
df %>%
  pivot_longer(cols = c("segment1", "segment2")) %>%
  filter(value == 1) %>%
  select(id, name)
2
Ben 11 may. 2020 a las 21:56

Utilice ifelse

with(DF, ifelse(segment1 == 1, "segment1", "segment2"))

library(dplyr)
DF %>%
  mutate(segment = if_else(segment1 == 1, "segment1", "segment2"))

1
Cole 11 may. 2020 a las 22:36