Перенесите множество замен Стата в R

#r #replace #stata #missing-data

Вопрос:

У меня есть пара тысяч строк кода Stata, который обычно направлен на замену отрицательных (отсутствующих) значений на правильное отсутствующее значение ( . ) от однорангового узла, и мне нужно перенести этот код в R. Для этого я взял код и сохранил его в виде одного столбца символьных строк. Замены, по сути, выглядят следующим образом, до тошноты:

 replace R04_ADULTTYPE = . if (R04_ADULTTYPE lt;= -1 )  

Это R04_ переменные в наборе данных, поэтому я надеюсь эффективно перенести эти строки состояния в R.

Я попытался взять это и отделить/заменить, чтобы легко перебрать список переменных, которые нуждаются в замене, но у меня заканчиваются идеи. Есть идеи о том, как легко перенести эти замены в массовом порядке в R, если они у меня есть в виде набора данных символьных строк? Мой ожидаемый результат, по сути, заключается в проведении многих замен Стата в R, которые я представил в данных ниже.

Ввод заголовка данных ( rawMissing ). Спасибо!

 # Data (many Stata replaces dput(head(rawMissing)) structure(list(replacements = c("replace R04_ADULTTYPE = . if (R04_ADULTTYPE lt;= -1 )",  "replace R04R_A_AT0047 = . if (R04R_A_AT0047 lt;= -1 )", "replace R04R_A_AM0069 = . if (R04R_A_AM0069 lt;= -1 )",  "replace R04R_A_AM0065_V2 = . if (R04R_A_AM0065_V2 lt;= -1 )",  "replace R04_AM0066 = . if (R04_AM0066 lt;= -1 )", "replace R04_AM0070 = . if (R04_AM0070 lt;= -1 )" )), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame" ))  # Expected output would be efficiently conducting these many replaces in R  

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

1. Я понимаю, что вы хотите заменить строку, а затем eval/parse каждую строку, чтобы изменить переменные в исходном объекте. Неясно, являются ли это R04_ADULTTYPE столбцы в другом объекте или нет. Как R это векторизовано, if деталь может быть ifelse или » заменить`

2. Да, R04 это переменные в другом контексте. Я надеюсь просто эффективно перенести тонну строк Stata в R. Я мог бы сделать некоторые замены строк для использования if или ifelse , но мне интересно, является ли это лучшим способом достижения цели.

3. Построчный перевод может быть неэффективным, так как оба языка могут иметь разную оптимизацию для каждого метода. Может быть, лучше ИМХО переписать код, взяв суть

4. Вроде того, чего я боялся, да. Считаете ли вы, что существует эффективное решение путем извлечения переменной ( R04 ), оператора ( lt;= или == ) и числового ( -1 ) в отдельных столбцах и массовой замены путем перебора столбцов?

5. @SimonPage хорошо, конечно. Я думаю, что мое решение должно работать (хотя оно не тестируется на реальных данных («df1»)).

Ответ №1:

Мы можем extract заменить имена столбцов, оператор и значение как отдельные столбцы

 library(dplyr) library(tidyr) keydat lt;- rawMissing %gt;%  extract(replacements, into = c('colnm', 'operator', 'value'),   '^[^(] \((\w )\s ([[:punct:]] )\s (-?[0-9] )')  

затем, используя приведенные выше данные, зациклите across исходный набор данных, скажем «df1», зациклив across столбцы, указанные в «keydat», и выполните необходимые действия replace

 df2 lt;- df1 %gt;%  mutate(across(all_of(keydat$colnm), ~   {  op lt;- keydat$operator[match(cur_column(), keydat$colnm)]  val lt;- keydat$value[match(cur_column(), keydat$colnm)]  replace(., match.fun(op)(., val), NA)      }))  

Ответ №2:

Альтернативой ответу @akrun было бы написать новый сценарий R, а затем создать этот сценарий. Это может быть полезно, например, для просмотра кода и точного документирования того, что было сделано (например, для анализа воспроизводимых данных и т. Д.). Я думаю, что обычно будет работать следующее: где statareplace.do имя файла исходного файла Stata, который нужно прочитать, и statareplace.R имя файла результирующего R-скрипта:

 fin lt;- "statareplace.do" fout lt;- "statareplace.R"  f lt;- readLines(fin) g lt;- gsub(  "^\w \s (\w )(\s )?=(\s )?. if\((. )\)$", "\1 = ifelse(\4", f ) g lt;- gsub(  "^\w \s (\w )(\s )?=(\s )?(. ) if(\s )?\((. )\)$",   "\1 = ifelse(\6, \4, \1),", f ) g lt;- gsub("\.", "NA", g) g  writeLines(c("library(dplyr)", "df lt;- df %gt;%", "mutate(", g, ")"), fout) source(fout)  

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

1. Отличная альтернатива! Я обязательно попробую и это: спасибо!