Объединить столбец, если дубликаты в строках между столбцами

У меня есть фрейм данных, например:

    COL1   COL2  COL3      COL4   COL5   COL6    COL7
1  Sp1-2  Sp1-2  Sp3_2-54  Sp3-2  Sp3-2  Sp3-2   SP9-43
2  Sp5-1  Sp5-2  Sp2-4     Sp9-2  Sp10-3 SP9-90  NA
3  Sp_7-3 Sp_7-3 NA        SP6-56 Sp2-7  SP3-3   NA

И я просто хотел бы объединить столбцы, когда дублируются хотя бы два элемента.

например, в COL1 и COL2, Sp1-2 и Sp_7-3 дублируются в обоих столбцах, тогда я объединяю их таким образом, добавляя вертикальную черту "|" между недублированными элементами:

   COL1|COL2     COL3      COL4|COL5|COL6       COL7
1  Sp1-2         Sp3_2-54  Sp3-2                SP9-43
2  Sp5-1|Sp5-2   Sp2-4     Sp9-2|Sp10-3|SP9-90  NA
3  Sp_7-3        NA        SP6-56|Sp2-7|SP3-3   NA

Вот формат dput:

structure(list(COL1 = c("Sp1-2", "Sp5-1", "Sp_7-3"), COL2 = c("Sp1-2", 
"Sp5-2", "Sp_7-3"), COL3 = c("Sp3_2-54", "Sp2-4", NA), COL4 = c("Sp3-2", 
"Sp9-2", "SP6-56"), COL5 = c("Sp3-2", "Sp10-3", "Sp2-7"), COL6 = c("Sp3-2", 
"SP9-90", "SP3-3"), COL7 = c("SP9-43", NA, NA)), class = "data.frame", row.names = c(NA, 
-3L))

Другой пример :

           G136             G348           G465
1          NA               NA             NA
2          NA               NA             NA
3          SP4-140          SP4-140        NA
4          SP2-8            NA             NA
5          SP3-59           NA             NA
6          SP1_contig.682-8 NA             SP1_contig.682-8

ожидаемый результат:

           G136|G348|G465
1          NA               
2          NA              
3          SP4-140          
4          SP2-8           
5          SP3-59           
6          SP1_contig.682-8 

формат заместителя:

dat<- structure(list(G136 = c(NA, NA, "SP4-140", "SP2-8", "SP3-59",  "SP1_contig.682-8", NA, NA, NA), G348 = c(NA, NA, "SP4-140",  NA, NA, NA, NA, NA, NA), G465 = c(NA, NA, NA, NA, NA, "SP1_contig.682-8",  NA, NA, NA)), row.names = c(NA, -9L), class = c("tbl_df", "tbl",  "data.frame"))

Есть ли только один набор столбцов с повторяющимися значениями?

Park 21.11.2022 08:32

Это может быть 2 или более столбца с повторяющимися значениями.

chippycentra 21.11.2022 08:32

Я улучшил пример, чтобы более подробно показать, что мне нужно

chippycentra 21.11.2022 08:36
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
0
3
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вероятно, лучше всего с этим справиться, сначала изменив форму ваших данных, а затем использовать различные группировки для достижения желаемого результата:

library(tidyr)
library(dplyr)

dat %>%
  rowid_to_column() %>%
  pivot_longer(-rowid) %>%
  filter(!is.na(value)) %>%
  group_by(rowid, value) %>%
  mutate(new_name = paste(name, collapse = "|")) %>%
  separate_rows(new_name, sep = "\\|") %>%
  group_by(name) %>%
  mutate(new_name = paste(unique(new_name), collapse = "|")) %>%
  group_by(value) %>%
  filter(nchar(new_name) == max(nchar(new_name))) %>%
  ungroup() %>%
  select(-name) %>%
  pivot_wider(names_from = new_name, values_from = value, values_fn = ~ paste(unique(.x), collapse = "|")) %>%
  complete(rowid = full_seq(c(1, rowid), 1))

# A tibble: 3 × 5
  rowid `COL1|COL2` COL3     `COL4|COL5|COL6`    COL7  
  <dbl> <chr>       <chr>    <chr>               <chr> 
1     1 Sp1-2       Sp3_2-54 Sp3-2               SP9-43
2     2 Sp5-1|Sp5-2 Sp2-4    Sp9-2|Sp10-3|SP9-90 NA    
3     3 Sp_7-3      NA       SP6-56|Sp2-7|SP3-3  NA     

И использование данных во втором примере дает:

# A tibble: 6 × 2
  rowid `G136|G348|G465`
  <dbl> <chr>           
1     1 NA              
2     2 NA              
3     3 SP4-140         
4     4 SP2-8           
5     5 SP3-59          
6     6 SP1_contig.682-8

Привет, спасибо, но, глядя на ваш код, я понимаю, что он также объединяет значения NA, но в этом случае его не следует воспринимать как повторяющиеся значения. Я отредактировал пример, чтобы он лучше соответствовал этому примеру, извините.

chippycentra 21.11.2022 09:04

Простое исправление — просто отфильтруйте NA значения после поворота — отредактируйте.

Ritchie Sacramento 21.11.2022 09:09

Я получаю это сообщение об ошибке: dat %>% Erreur : Problem with `mutate()` column `new_name`. ℹ `new_name = unique(new_name[nchar(new_name) == max(nchar(new_name))])`. ℹ `new_name` must be size 4 or 1, not 2. ℹ The error occurred in group 42: name = "G136".. на этапе мутации у вас есть идея?

chippycentra 21.11.2022 09:11

Вот формат dput части, содержащей ошибку, если вы можете посмотреть на нее? : dat<- structure(list(G136 = c(NA, NA, "SP4-140", "SP2-8", "SP3-59", "SP1_contig.682-8", NA, NA, NA), G348 = c(NA, NA, "SP4-140", NA, NA, NA, NA, NA, NA), G465 = c(NA, NA, NA, NA, NA, "SP1_contig.682-8", NA, NA, NA)), row.names = c(NA, -9L), class = c("tbl_df", "tbl", "data.frame"))

chippycentra 21.11.2022 09:22

Проблема в том, что столбцы перекрываются с разными столбцами в разных строках, то есть у вас может быть перекрытие C1/C2 в строке 1 и C1/C3 в строке 2. Как вы ожидаете, что результат должен быть здесь?

Ritchie Sacramento 21.11.2022 09:41

Я ожидаю объединить все эти столбцы, я отредактировал еще один пример в конце, чтобы дать вам ожидаемый результат, спасибо

chippycentra 21.11.2022 09:45

Спасибо, теперь в части pivot_wider я получаю следующее сообщение: Error : `values_fn` must be a NULL, a function, or a named list

chippycentra 21.11.2022 10:00

Я понимаю это с двумя примерами

chippycentra 21.11.2022 10:17

ОК, теперь это работает, я добавляю в обновленные свои пакеты....

chippycentra 21.11.2022 10:59

Это действительно грязно... но вы можете попробовать

library(igraph)
library(stringdist)
library(data.table)


table(df[1,])

d <- c()
for (i in 1:(ncol(df)-1)){
  for (j in (i+1):ncol(df)) {
    if(any(na.omit(stringdist(df[,i], df[,j], method = "lv") == 0))) {
      d <- rbind(d, c(i,j))
    }
  }
}
dd <- data.table(d)

net <- graph_from_data_frame(d = dd, directed = F)
key <- split(names(V(net)), components(net)$membership)
res <- matrix(NA,nrow = nrow(df), ncol = 0)
names_dummy <- c()
df_dummy <- c()
for (i in key){
  i <- as.numeric(i)
  names_dummy <- c(names_dummy, paste0(colnames(df)[i], collapse = "|"))
  df_dummy <- cbind(df_dummy, apply(df[,i], 1, function(x) {paste0(unique(unlist(x)), collapse = "|")}))
  
  
}
colnames(df_dummy) <- names_dummy
df_dummy



res <- cbind(df_dummy, df[,-as.numeric(unlist(key))])
res <- res[,sort(colnames(res))]
res

    COL1|COL2     COL3      COL4|COL5|COL6   COL7
1       Sp1-2 Sp3_2-54               Sp3-2 SP9-43
2 Sp5-1|Sp5-2    Sp2-4 Sp9-2|Sp10-3|SP9-90   <NA>
3      Sp_7-3     <NA>  SP6-56|Sp2-7|SP3-3   <NA>

Другие вопросы по теме