Разбивка нескольких столбцов на два столбца и удаление дубликатов в R

#r

#r

Вопрос:

У меня есть несколько столбцов, но здесь приведена только часть моих данных:

 df<-read.table (text=" Color1   Size1   Color2  Size2   Color3  Size3
Yellow  AA  Gray    GB  Purpul  MO
Blue    BD  Cyne    CE  Gray    GB
Yellow  AA  Yellow  AA  Black   LL
Red MD  Reddark KK  Reddark KK
Green   MC  Reddark KK  Green   MC
", header=TRUE)
 

Я хочу вывести все столбцы и отобразить их в виде двух столбцов, а затем удалить дубликаты, чтобы получить эту таблицу:

 Color   Size
Yellow  AA
Blue    BD
Red MD
Green   MC
Gray    GB
Cyne    CE
Reddark KK
Purpul  MO
Black   LL
 

Я пытаюсь изменить форму 2 с помощью melt, но мне было трудно это сделать.

Ответ №1:

Без каких-либо других библиотек reshape и unique могут выполнить эту работу:

 > unique(reshape(df, varying=1:6, direction="long", v.names=c("Color", "Size"), timevar=NULL)[1:2])
      Color Size
1.1  Yellow   AA
2.1    Blue   BD
4.1     Red   MD
5.1   Green   MC
1.2    Gray   GB
2.2    Cyne   CE
4.2 Reddark   KK
1.3  Purpul   MO
3.3   Black   LL
 

Поворот кажется мне излишеством, но что я знаю? Если индекс вас беспокоит (хотя он сохраняет информацию о том, как была структурирована широкая таблица), сбросьте имена строк:

 > uniq = unique(reshape(df, varying=1:6, direction="long", v.names=c("Color", "Size"), timevar=NULL)[1:2])
> rownames(uniq) = NULL
 

Ответ №2:

Другой способ использования pivot_longer() и pivot_wider() может быть:

 library(dplyr)
library(tidyr)
#Code
newdf <- df %>%
  pivot_longer(everything()) %>%
  mutate(name=substr(name,1,nchar(name)-1)) %>%
  group_by(name) %>% mutate(id2=row_number()) %>%
  pivot_wider(names_from = name,values_from=value) %>%
  select(-id2) %>%
  filter(!duplicated(paste(Color,Size)))
 

Вывод:

 # A tibble: 9 x 2
  Color   Size 
  <fct>   <fct>
1 Yellow  AA   
2 Gray    GB   
3 Purpul  MO   
4 Blue    BD   
5 Cyne    CE   
6 Black   LL   
7 Red     MD   
8 Reddark KK   
9 Green   MC  
 

Комментарии:

1. @user330 Тоже отличный вопрос 1

Ответ №3:

Мы можем использовать pivot_longer from tidyr для изменения формы с ‘wide’ на ‘long’ в двух столбцах, указав в names_sep качестве границы между буквой и цифрой ( (?<=[a-z])(?=\d) ) в именах столбцов, а затем взять distinct из двух столбцов

 library(dplyr)
library(tidyr)
pivot_longer(df, cols = everything(),
     names_to = c( '.value', 'grp'), names_sep="(?<=[a-z])(?=\d)") %>% 
   distinct(Color, Size)
 

-вывод

 # A tibble: 9 x 2
#  Color   Size 
#  <chr>   <chr>
#1 Yellow  AA   
#2 Gray    GB   
#3 Purpul  MO   
#4 Blue    BD   
#5 Cyne    CE   
#6 Black   LL   
#7 Red     MD   
#8 Reddark KK   
#9 Green   MC   
 

Или с помощью data.table

 library(data.table)
unique(melt(setDT(df), measure = patterns('^Color', '^Size'),
       value.name = c('Color', 'Size'))[, variable := NULL])
#     Color Size
#1:  Yellow   AA
#2:    Blue   BD
#3:     Red   MD
#4:   Green   MC
#5:    Gray   GB
#6:    Cyne   CE
#7: Reddark   KK
#8:  Purpul   MO
#9:   Black   LL
 

данные

 df <- structure(list(Color1 = c("Yellow", "Blue", "Yellow", "Red", 
"Green"), Size1 = c("AA", "BD", "AA", "MD", "MC"), Color2 = c("Gray", 
"Cyne", "Yellow", "Reddark", "Reddark"), Size2 = c("GB", "CE", 
"AA", "KK", "KK"), Color3 = c("Purpul", "Gray", "Black", "Reddark", 
"Green"), Size3 = c("MO", "GB", "LL", "KK", "MC")), 
class = "data.frame", row.names = c(NA, 
-5L))
 

Комментарии:

1. Ошибка: distinct() необходимо использовать существующие переменные

2. @user330 Основываясь на данных, которые вы показали, он работает правильно для меня