Информация, разделенная запятыми, в одной ячейке

У меня есть набор данных в R с беспорядочными данными, где информация о тестах каждого человека хранится в отдельных соответствующих столбцах: имя_теста, результат_теста и статус_теста. Все три столбца содержат значения, разделенные запятыми, для каждого теста, если было выполнено более одного теста. Я хочу извлечь отдельные тесты, соответствующие им результаты и статусы для каждого человека наиболее эффективным способом. Моя конечная цель — иметь возможность проводить различные тесты, их результаты и статус для каждого человека. Это образец данных.

dput(tb_sample_10)
structure(list(test_name = c("TB Direct PCR & RIF Status,AFB Smear", 
"AFB Smear,Sensitivity,TB Direct PCR & RIF Status,TB Indirect PCR & RIF Status,Culture", 
"Culture,AFB Smear,Sensitivity,TB Direct PCR & RIF Status,TB Indirect PCR & RIF Status", 
"AFB Smear", "Culture,AFB Smear,Sensitivity,TB Direct PCR & RIF Status,TB Indirect PCR & RIF Status", 
"Culture,AFB Smear,Sensitivity,TB Direct PCR & RIF Status,TB Indirect PCR & RIF Status", 
"AFB Smear,TB Direct PCR & RIF Status", "Culture,AFB Smear,Sensitivity,TB Direct PCR & RIF Status,TB Indirect PCR & RIF Status", 
"AFB Smear,TB Direct PCR & RIF Status", "TB Direct PCR & RIF Status,Culture"
), test_result = c("MTB Detected / RIF Resistance Not Detected,No AFB Seen", 
"OTHER,Not Required,MTB Detected / RIF Resistance Not Detected,Not Required,No Growth", 
"Positive,No AFB Seen,Processed,Rejected,MTB Detected / RIF Resistance Not Detected (MTBC)", 
"AFB+", "Positive,OTHER,Processed,MTB Not Detected,Not Required", 
"Positive,AFB+,Not Required,MTB Detected / RIF Resistance Not Detected,Not Required", 
"No AFB Seen,MTB Detected / RIF Resistance Not Detected", "No Growth,No AFB Seen,Not Required,MTB Detected / RIF Resistance Not Detected,Not Required", 
"No AFB Seen,MTB Not Detected", "MTB Detected / RIF Resistance Not Detected,Positive"
), test_status = c("Final,Final", "Final,Final,Final,Final,Final", 
"Final,Final,Final,Final,Final", "Final", "Final,Final,Final,Final,Final", 
"Final,Final,Final,Final,Final", "Final,Final", "Final,Final,Final,Final,Final", 
"Final,Final", "Final,Final")), row.names = c(NA, -10L), class = c("tbl_df", 
"tbl", "data.frame"))

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
71
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Использование функций tidyverse согласно тегу вопроса:

library(dplyr)
library(tidyr)

tb_sample_10 %>%
  mutate(ID = row_number()) %>%
  rowwise() %>%
  transmute(ID = ID,
            names = list(strsplit(test_name, ",")),
            results = list(strsplit(test_result, ",")),
            statuses = list(strsplit(test_status, ","))) %>%
unnest(cols = c(names, results, statuses)) %>%
unnest(cols = c(names, results, statuses))
# A tibble: 34 × 4
      ID names                        results                                           statuses
   <int> <chr>                        <chr>                                             <chr>
 1     1 TB Direct PCR & RIF Status   MTB Detected / RIF Resistance Not Detected        Final
 2     1 AFB Smear                    No AFB Seen                                       Final
 3     2 AFB Smear                    OTHER                                             Final
 4     2 Sensitivity                  Not Required                                      Final
 5     2 TB Direct PCR & RIF Status   MTB Detected / RIF Resistance Not Detected        Final
 6     2 TB Indirect PCR & RIF Status Not Required                                      Final
 7     2 Culture                      No Growth                                         Final
 8     3 Culture                      Positive                                          Final
 9     3 AFB Smear                    No AFB Seen                                       Final
10     3 Sensitivity                  Processed                                         Final
11     3 TB Direct PCR & RIF Status   Rejected                                          Final
12     3 TB Indirect PCR & RIF Status MTB Detected / RIF Resistance Not Detected (MTBC) Final
13     4 AFB Smear                    AFB+                                              Final
14     5 Culture                      Positive                                          Final
15     5 AFB Smear                    OTHER                                             Final
16     5 Sensitivity                  Processed                                         Final
17     5 TB Direct PCR & RIF Status   MTB Not Detected                                  Final
18     5 TB Indirect PCR & RIF Status Not Required                                      Final
19     6 Culture                      Positive                                          Final
20     6 AFB Smear                    AFB+                                              Final
# ℹ 14 more rows

Обратите внимание: я создал столбец ID просто для того, чтобы следить за происходящим. Возможно, он уже есть в ваших данных, или вы все равно можете обойтись без него.

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

Вы можете использовать str_split, enframe и unnest, чтобы разделить три объекта. Затем объедините их, используя inner_join.

library(dplyr); library(tidyr); library(stringr)

tests <- str_split(tb_sample_10$test_name, pattern = ",") |>
  enframe(name = "id", value = "test") |>
  unnest(test) |>
  mutate(seq=row_number(), .by=id) |>
  select(id, seq, test)

results <- str_split(tb_sample_10$test_result, pattern = ",") |>
  enframe(name = "id", value = "result") |>
  unnest(result) |>
  mutate(seq=row_number(), .by=id)

statuses <- str_split(tb_sample_10$test_status, pattern = ",") |>
  enframe(name = "id", value = "status") |>
  unnest(status) |>
  mutate(seq=row_number(), .by=id)

Reduce(inner_join, list(tests, results, statuses))
# A tibble: 34 x 5
      id   seq test                         result                                     status
   <int> <int> <chr>                        <chr>                                      <chr> 
 1     1     1 TB Direct PCR & RIF Status   MTB Detected / RIF Resistance Not Detected Final 
 2     1     2 AFB Smear                    No AFB Seen                                Final 
 3     2     1 AFB Smear                    OTHER                                      Final 
 4     2     2 Sensitivity                  Not Required                               Final 
 5     2     3 TB Direct PCR & RIF Status   MTB Detected / RIF Resistance Not Detected Final 
 6     2     4 TB Indirect PCR & RIF Status Not Required                               Final 
 7     2     5 Culture                      No Growth                                  Final 
 8     3     1 Culture                      Positive                                   Final 
 9     3     2 AFB Smear                    No AFB Seen                                Final 
10     3     3 Sensitivity                  Processed                                  Final 
# i 24 more rows

Вы можете сделать это с помощью tidyr::separate_longer_delim() . Это было выпущено в tidyr 1.3.0 (январь 2023 г.):

Самая большая особенность этого выпуска — новое экспериментальное семейство функций для разделения строковых столбцов.

Эта функция отмечена жизненным циклом экспериментальная, что означает, что долгосрочная стабильность не обещается. Тем не менее, он существует уже больше года и, похоже, создан именно для вашего случая.

Я также добавил столбец id, который не нужен для разделения строк, но может быть полезен для отслеживания того, к какой из исходных 10 строк относится каждая из теперь 34 строк.

tb_sample_10 |>
    dplyr::mutate(id = dplyr::row_number(), .before = test_name) |>
    tidyr::separate_longer_delim(
        cols = dplyr::starts_with("test"),
        delim = ","
    )

# # A tibble: 34 × 4
#       id test_name                    test_result                    test_status
#    <int> <chr>                        <chr>                          <chr>      
#  1     1 TB Direct PCR & RIF Status   MTB Detected / RIF Resistance… Final      
#  2     1 AFB Smear                    No AFB Seen                    Final      
#  3     2 AFB Smear                    OTHER                          Final      
#  4     2 Sensitivity                  Not Required                   Final      
#  5     2 TB Direct PCR & RIF Status   MTB Detected / RIF Resistance… Final      
#  6     2 TB Indirect PCR & RIF Status Not Required                   Final      
#  7     2 Culture                      No Growth                      Final      
#  8     3 Culture                      Positive                       Final      
#  9     3 AFB Smear                    No AFB Seen                    Final      
# 10     3 Sensitivity                  Processed                      Final      
# # ℹ 24 more rows
# # ℹ Use `print(n = ...)` to see more rows

Используя data.table, разделите столбцы 1, 2 и 3 запятыми и добавьте новую строку. Обратите внимание, что я добавляю столбец I, чтобы отслеживать идентификаторы строк.

tb_sample_10[, lapply(.SD, \(i) unlist(tstrsplit(i, ","))), by = .I, .SDcols = 1:3 ]

#        I                    test_name                                test_result test_status
#    <int>                       <char>                                     <char>      <char>
# 1:     1   TB Direct PCR & RIF Status MTB Detected / RIF Resistance Not Detected       Final
# 2:     1                    AFB Smear                                No AFB Seen       Final
# 3:     2                    AFB Smear                                      OTHER       Final
# 4:     2                  Sensitivity                               Not Required       Final
# 5:     2   TB Direct PCR & RIF Status MTB Detected / RIF Resistance Not Detected       Final
# 6:     2 TB Indirect PCR & RIF Status                               Not Required       Final
# 7:     2                      Culture                                  No Growth       Final
# 8:     3                      Culture                                   Positive       Final
# 9:     3                    AFB Smear                                No AFB Seen       Final
#10:     3                  Sensitivity                                  Processed       Final

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