#r #group-by #count
#r #группировка по #подсчет
Вопрос:
Я работаю с некоторыми клиническими данными, и я хотел бы подсчитать количество проведенных кем-то тестов, которые были «Не обнаружены» до того, как у них был «Обнаруженный» результат, и исключить всех, у кого никогда не было «обнаруженного» результата.
ID <- c(1,1,2,2,3,3,3,4)
Specimen_Type <- c("NP", "NP", "Throat", "Throat", "NP", "Throat", "Throat", "NP")
RESULT_VAL <- c("Not Detected", "Detected", "Not Detected", "Detected", "Not Detected", "Not Detected", "Detected", "Not Detected")
RESULT_DATE <- c("6-1-2020", "6-10-2020","6-1-2020", "6-10-2020","6-1-2020", "6-10-2020", "6-20-2020", "6-1-2020")
Data_sum<- data.frame(ID, Specimen_Type, RESULT_VAL, RESULT_DATE)
Я хотел бы, чтобы результат выглядел так (или что-то вроде этого), потому что я также хотел бы видеть, сколько разных типов образцов использовалось для тестирования до получения положительного результата.
ID Number_of_tests_before_pos Specimen_Type
1 1 NP
2 1 Throat
3 2 NP,Throat
Ответ №1:
Вот базовый вариант R
transform(
aggregate(
. ~ ID,
cbind(
subset(Data_sum,
ave(RESULT_VAL == "Detected", ID, FUN = function(x) cumsum(x) == 0 amp; any(x)),
select = c(ID, Specimen_Type)
),
Number_of_tests_before_pos = 1
),
c
),
Number_of_tests_before_pos = lengths(Number_of_tests_before_pos)
)
предоставление
ID Specimen_Type Number_of_tests_before_pos
1 1 NP 1
2 2 Throat 1
3 3 NP, Throat 2
Ответ №2:
После группировки по ‘ID’, используйте match
для получения индекса первого вхождения ‘Detected’ в ‘RESULT_VAL’ (‘i1’), если совпадения нет, по умолчанию возвращает NA
, используйте эту информацию для удаления идентификаторов filter
, затем мы используем summarise
для получения количества ‘NotОбнаружено’ в подмножестве ‘RESULT_VAL’ до этого индекса, аналогично paste
unique
элементам ‘sample_type’ в данных подмножества
library(dplyr)
Data_sum %>%
group_by(ID) %>%
mutate(i1 = match('Detected', RESULT_VAL)) %>%
filter(complete.cases(i1)) %>%
summarise(Number_of_tests_before_pos = sum(RESULT_VAL[seq(i1[1])] ==
'Not Detected'),
Specimen_Type = toString(unique(Specimen_Type[seq(i1[1])])),
.groups = 'drop')
-вывод
# A tibble: 3 x 3
# ID Number_of_tests_before_pos Specimen_Type
# <dbl> <int> <chr>
#1 1 1 NP
#2 2 1 Throat
#3 3 2 NP, Throat
Или мы можем использовать cumsum
логический вектор для выполнения filter
редактирования
Data_sum %>%
group_by(ID) %>%
filter(cumsum(RESULT_VAL == 'Detected') < 1,
any(RESULT_VAL == 'Detected')) %>%
summarise(Number_of_tests_before_pos = sum(RESULT_VAL == 'Not Detected'),
Specimen_Type = toString(unique(Specimen_Type)), .groups = 'drop')
# A tibble: 3 x 3
# ID Number_of_tests_before_pos Specimen_Type
# <dbl> <int> <chr>
#1 1 1 NP
#2 2 1 Throat
#3 3 2 NP, Throat
Ответ №3:
Вы можете сначала удалить все ID
, что не имеет 'Detected'
in RESULT_VAL
, подсчитать количество строк до 'Detected'
и объединить Specimen_Type
в строку, разделенную одной запятой.
library(dplyr)
Data_sum %>%
group_by(ID) %>%
filter(any(RESULT_VAL == 'Detected')) %>%
summarise(n = match('Detected', RESULT_VAL) - 1,
Specimen_Type = toString(Specimen_Type[1:n]))
# ID n Specimen_Type
# <dbl> <dbl> <chr>
#1 1 1 NP
#2 2 1 Throat
#3 3 2 NP, Throat