Как классифицировать несколько объектов в фрейме данных R - PullRequest
0 голосов
/ 09 мая 2018

Это лишь небольшая часть фрейма данных, с которым я работаю:

id       drug        start        stop          dose    unit    route   
2010003  Amlodipine  2009-02-04   2009-11-19    1.5     mg      Oral    
2010003  Amlodipine  2009-11-19   2010-01-11    1.5     mg      Oral      
2010004  Cefprozil   2004-03-12   2004-03-19    175     mg      Oral    
2010004  Clobazam    2002-12-30   2003-01-01    5       mg      Oral

У меня есть файл Stata do, который показывает, что я пытаюсь сделать:

replace class = "ACE Inhibitor" if strmatch(upper(drug), "CAPTOPRIL*")
replace class = "ACE Inhibitor" if strmatch(upper(drug), "ENALAPRIL*")
replace class = "ACE Inhibitor" if strmatch(upper(drug), "ENALAPRILAT*")
replace class = "ACE Inhibitor" if strmatch(upper(drug), "FOSINOPRIL*")
replace class = "ACE Inhibitor" if strmatch(upper(drug), "LISINOPRIL*")
replace class = "ACE Inhibitor" if strmatch(upper(drug), "RAMIPRIL*")
replace class = "Acne Medication" if strmatch(upper(drug), "ADAPALENE*")
replace class = "Acne Medication" if strmatch(upper(drug), "ADAPALENE/BENZOYL PEROXIDE*")
replace class = "Acne Medication" if strmatch(upper(drug), "BENZOYL PEROXIDE*")
replace class = "Acne Medication" if strmatch(upper(drug), "BENZOYL PEROXIDE/CLINDAMYCIN*")
replace class = "Acne Medication" if strmatch(upper(drug), "ISOTRETINOIN*")
replace class = "Acne Medication" if strmatch(upper(drug), "ERYTHROMYCIN/TRETINOIN*")
replace class = "Acne Medication/Acute Promyelocytic Leukemia Medication" if strmatch(upper(drug), "TRETINOIN*")
replace class = "Alpha Agonist" if strmatch(upper(drug), "XYLOMETAZOLINE*")
replace class = "Alpha Blocker" if strmatch(upper(drug), "DOXAZOSIN*")
replace class = "Alpha Blocker" if strmatch(upper(drug), "PHENOXYBENZAMINE*")
replace class = "Alpha Blocker" if strmatch(upper(drug), "PHENTOLAMINE*")
replace class = "Alpha Blocker" if strmatch(upper(drug), "PRAZOSIN*")
replace class = "Alpha Blocker" if strmatch(upper(drug), "TAMSULOSIN*")
replace class = "Alpha Blocker" if strmatch(upper(drug), "TERAZOSIN*")
replace class = "Alpha/Beta Blocker" if strmatch(upper(drug), "CARVEDILOL*")
replace class = "Alpha/Beta Blocker" if strmatch(upper(drug), "LABETALOL*")
replace class = "Alpha-1 Agonist" if strmatch(upper(drug), "PHENYLEPHRINE*")
replace class = "Alpha-1 Agonist" if strmatch(upper(drug), "MIDODRINE*")
replace class = "Alpha-2 Agonist" if strmatch(upper(drug), "CLONIDINE*")
replace class = "Alpha-2 Agonist" if strmatch(upper(drug), "DEXMEDETOMIDINE*")
replace class = "Anaesthetic, general" if strmatch(upper(drug), "KETAMINE*")
replace class = "Anaesthetic, general" if strmatch(upper(drug), "THIOPENTAL*")
replace class = "Anaesthetic, local" if strmatch(upper(drug), "BENZOCAINE*")
replace class = "Anaesthetic, local" if strmatch(upper(drug), "BUPIVACAINE*")
replace class = "Anaesthetic, local" if strmatch(upper(drug), "BUPIVACAINE/FENTANYL*")
replace class = "Anaesthetic, local" if strmatch(upper(drug), "TETRACAINE*")
replace class = "Anaesthetic, local" if strmatch(upper(drug), "XYLOCAINE*")
replace class = "Anaesthetic, local/Antiarrythmic" if strmatch(upper(drug), "LIDOCAINE*")
replace class = "Anaesthetic, local/Antiseptic" if strmatch(upper(drug), "HEXYLRESORCINOL*")
replace class = "Anaesthetic, topical" if strmatch(upper(drug), "LIDOCAINE/PRILOCAINE*")
replace class = "Anaesthetic, topical" if strmatch(upper(drug), "PROPARACAINE*")
replace class = "Analgesic" if strmatch(upper(drug), "ACETAMINOPHEN*")
replace class = "Analgesic" if strmatch(upper(drug), "BELLADONNA & OPIUM SUPPOSITORY*")

Я хочу сделать ту же классификацию в R, но я не знаю Stata.

Обратите внимание, что наркотики могут иметь более одного class.

Любой совет и помощь будут с благодарностью.

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Предположим, что statscript и DF воспроизводятся в примечании в конце. Затем извлеките класс и шаблон в translate и оставьте соединение DF с ним, используя шаблон glob pat.

translate <- read.table(text = statascript, as.is = TRUE)[c(4, 7)]
names(translate) <- c("class", "pat")

library(sqldf)
sqldf("select DF.*, translate.class 
       from DF 
       left join translate on upper(class) glob pat")

Примечание

# just first few lines for illustration
Lines <- '
replace class = "ACE Inhibitor" if strmatch(upper(drug), "CAPTOPRIL*")
replace class = "ACE Inhibitor" if strmatch(upper(drug), "ENALAPRIL*")
replace class = "ACE Inhibitor" if strmatch(upper(drug), "ENALAPRILAT*")
'

Lines2 <- "
id       drug        start        stop          dose    unit    route   
2010003  Amlodipine  2009-02-04   2009-11-19    1.5     mg      Oral    
2010003  Amlodipine  2009-11-19   2010-01-11    1.5     mg      Oral      
2010004  Cefprozil   2004-03-12   2004-03-19    175     mg      Oral    
2010004  Clobazam    2002-12-30   2003-01-01    5       mg      Oral"

statascript <- readLines(textConnection(Lines))
DF <- read.table(text = Lines2, header = TRUE, as.is = TRUE)
0 голосов
/ 09 мая 2018

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

drug_class_data <- read.table("Desktop/stata_script", header=FALSE, sep='"',stringsAsFactors = FALSE)  
drug_class_data <-drug_class_data[,c(2,4)] 
colnames(drug_class_data) <- c('Drug_class','Drug')

Удалить трейлинг * - используется в качестве символа подстановки в скрипте Stata

drug_class_data$Drug = gsub("\\*", "", drug_class_data$Drug)

Это дает вам фрейм данных с 2 столбцами ('Drug_class' & 'Drug') - строка извлекает любые данные в кавычках из каждой строки скрипта Stata (выделено жирным шрифтом ниже):

replace class = " ACE Inhibitor ", если strmatch (верхний (препарат), " CAPTOPRIL *")

Я бы затем сохранил это как файл, который затем можно будет импортировать по мере необходимости (я предполагаю, что эти данные еще не доступны, как это, поскольку вы жестко закодировали все эти значения в примере Stata).

write.csv(drug_class_data, file = "drug_class_data.csv",row.names=FALSE)

Оттуда зависит, хотите ли вы:

1) Несколько строк для каждого экземпляра препарата с одним текстовым столбцом, где класс препарата указан явно. Количество рядов на препарат = количество классов наркотиков, членом которых он является. У этого подхода есть некоторые преимущества, но он приводит к большому количеству дублированных данных.

2) Одна строка для каждого лекарственного средства и несколько логических столбцов для каждого класса лекарств - «Ингибитор АПФ», «Препарат от угревой сыпи» и т. Д. - содержащие двоичный ИСТИНА или ЛОЖЬ, чтобы указать, является ли он членом этого класса.

Лично я предпочел бы вариант 2 в качестве отправной точки для последующего анализа. (Поскольку вы упоминаете, что наркотики могут быть отнесены к нескольким классам, также несколько классов наркотиков выглядят иерархически - «Анестетик, местный» может быть родительским термином для «Анестетик, местный / антиаритмический», «Анестетик, местный / антисептик» и т. Д.)

Извлеките все уникальные классы лекарств из вашего фрейма данных в список:

drug_class_list <- unique(drug_class_data[,1])

Затем я использовал бы уродливый код ниже для создания нового кадра данных:

create_flat_table <- function(df_drugs, df_classes){   
# Extract list of drug classes present in df

class_list <- unique(df_classes[,1])  
# Reiterate over this list creating a new column in the drug df and populating it with data   
drugs <- as.list(drug_data['drug'])  
results <- df_drugs   
for(class in class_list){   
class_drugs <- df_classes[df_classes$Drug_class == class,]   
boolean_list <- toupper(df_drugs[,2])%in%class_drugs[,2]
results <- cbind(results, boolean_list )   }   
colnames(results) <- c(colnames(df_drugs), class_list)   
return(results) }

combined_df <- create_flat_table(drug_data, drug_class_data)

Полученный кадр данных будет выглядеть так:

Resulting Dataframe

Обратите внимание, что в этом примере я изменил данные так, чтобы хотя бы одно лекарство из вашего набора игрушечных данных соответствовало классу в вашем сокращенном списке классов лекарств.

...