Как установить подкадр данных на основе критериев «не равно», применяемых к большому количеству столбцов? - PullRequest
9 голосов
/ 29 марта 2019

Я новичок в R и в настоящее время пытаюсь установить свои данные в соответствии с моими предопределенными критериями исключения для анализа. В настоящее время я пытаюсь удалить все случаи, которые имеют деменцию, как закодировано МКБ-10. Проблема заключается в том, что существует несколько переменных, содержащих информацию о состоянии болезни каждого индивидуума (~ 70 переменных), хотя, поскольку они закодированы одинаково, ко всем из них может применяться одинаковое условие.

Некоторые смоделированные данные:

#Create dataframe containing simulated data
df = data.frame(ID = c(1001, 1002, 1003, 1004, 1005,1006,1007,1008,1009,1010,1011),
                    disease_code_1 = c('I802','H356','G560','D235','B178','F011','F023','C761','H653','A049','J679'),
                    disease_code_2 = c('A071','NA','G20','NA','NA','A049','NA','NA','G300','G308','A045'),
                    disease_code_3 = c('H250','NA','NA','I802','NA','A481','NA','NA','NA','NA','D352'))

#data is structured as below:

     ID disease_code_1 disease_code_2 disease_code_3
1  1001           I802           A071           H250
2  1002           H356             NA             NA
3  1003           G560            G20             NA
4  1004           D235             NA           I802
5  1005           B178             NA             NA
6  1006           F011           A049           A481
7  1007           F023             NA             NA
8  1008           C761             NA             NA
9  1009           H653           G300             NA
10 1010           A049           G308             NA
11 1011           J679           A045           D352


Здесь я пытаюсь удалить любой случай, у которого есть «код слабоумия» в любой из переменных «болезнь_кода».

#Remove cases with dementia from dataframe (e.g. F023, G20)
Newdata_df <- subset(df, (2:4 != "F023"|"G20"|"F009"|"F002"|"F001"|"F000"|"F00"|    
                    "G309"| "G308"|"G301"|"G300"|"G30"| "F01"|"F018"|"F013"|
                    "F012"| "F011"| "F010"|"F01"))

Ошибка, которую я получаю:

Error in 2:4 != "F023" | "G20" : 
  operations are possible only for numeric, logical or complex types

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

     ID disease_code_1 disease_code_2 disease_code_3
1  1001           I802           A071           H250
2  1002           H356             NA             NA
4  1004           D235             NA           I802
5  1005           B178             NA             NA
8  1008           C761             NA             NA
11 1011           J679           A045           D352

Я знаю, что в моем коде есть ошибка, хотя я не уверен, как именно это исправить. Я пробовал несколько других способов (используя dplyr), но пока мне не повезло.

Любая помощь очень ценится!

Ответы [ 6 ]

4 голосов
/ 29 марта 2019

Мы можем создать вектор с удаляемыми кодами и использовать rowSums для удаления, т.е.

codes_to_remove <- c("F023", "G20", "F009", "F002", "F001", "F000", "F00", "G309", "G308",
                "G301", "G300", "G30", "F01", "F018", "F013", "F012", "F011", "F010", "F01")

df[rowSums(sapply(df[-1], `%in%`, codes_to_remove)) == 0,]

что дает,

     ID disease_code_1 disease_code_2 disease_code_3
1  1001           I802           A071           H250
2  1002           H356             NA             NA
4  1004           D235             NA           I802
5  1005           B178             NA             NA
8  1008           C761             NA             NA
11 1011           J679           A045           D352
3 голосов
/ 29 марта 2019

Мы можем использовать melt/dcast от data.table

library(data.table)
dcast(melt(setDT(df), id.var = 'ID')[,
     if(!any(value %in% dementia_codes)) .SD, .(ID)], ID ~ variable)
#    ID disease_code_1 disease_code_2 disease_code_3
#1: 1001           I802           A071           H250
#2: 1002           H356             NA             NA
#3: 1004           D235             NA           I802
#4: 1005           B178             NA             NA
#5: 1008           C761             NA             NA
#6: 1011           J679           A045           D352

Или это можно сделать более компактно в base R без изменения формы

df[!Reduce(`|`, lapply(df[-1], `%in%` , dementia_codes)),]
 #   ID disease_code_1 disease_code_2 disease_code_3
#1  1001           I802           A071           H250
#2  1002           H356             NA             NA
#4  1004           D235             NA           I802
#5  1005           B178             NA             NA
#8  1008           C761             NA             NA
#11 1011           J679           A045           D352

Данные

dementia_codes <- c("F023", "G20", "F009", "F002", "F001", "F000", 
  "F00", "G309", "G308", "G301", "G300", "G30", "F01", "F018", "F013", 
   "F012", "F011", "F010", "F01")
3 голосов
/ 29 марта 2019

Как уже упоминалось в комментариях @docendo discimus, мы можем преобразовать фрейм данных в длинный формат, используя gather, group_by ID и выбрать только те ID, в которых нет dementia_code, а затем spread их обратно в широкоформатный формат.

library(tidyverse)

df %>%
   gather(key, value, -ID) %>%
   group_by(ID) %>%
   filter(!any(value %in% dementia_code)) %>%
   spread(key, value)

#   ID disease_code_1 disease_code_2 disease_code_3
#  <dbl> <chr>          <chr>          <chr>         
#1  1001 I802           A071           H250          
#2  1002 H356           NA             NA            
#3  1004 D235           NA             I802          
#4  1005 B178           NA             NA            
#5  1008 C761           NA             NA            
#6  1011 J679           A045           D352          

данные

dementia_code <- c("F023", "G20", "F009", "F002", "F001", "F000", "F00", "G309", 
"G308","G301", "G300", "G30", "F01", "F018", "F013", "F012", "F011", "F010", "F01")
3 голосов
/ 29 марта 2019

Одна dplyr возможность может быть:

df %>%
 filter_at(vars(2:4), all_vars(! . %in% c("F023","G20","F009","F002","F001","F000","F00",    
            "G309", "G308","G301","G300","G30", "F01","F018","F013",
            "F012", "F011", "F010","F01")))

    ID disease_code_1 disease_code_2 disease_code_3
1 1001           I802           A071           H250
2 1002           H356             NA             NA
3 1004           D235             NA           I802
4 1005           B178             NA             NA
5 1008           C761             NA             NA
6 1011           J679           A045           D352

В этом случае проверяется, содержит ли какой-либо из приведенных кодов какой-либо из столбцов 2: 4.

Или:

df %>%
 filter_at(vars(contains("disease_code")), all_vars(! . %in% c("F023","G20","F009","F002","F001","F000","F00",    
            "G309", "G308","G301","G300","G30", "F01","F018","F013",
            "F012", "F011", "F010","F01")))

В этом случае он проверяет, содержит ли какой-либо из столбцов с именами disease_code какой-либо из указанных кодов.

3 голосов
/ 29 марта 2019

Как насчет этого:

> dementia <- c("F023", "G20", "F009", "F002", "F001", "F000", "F00", "G309", "G308",
+               "G301", "G300", "G30", "F01", "F018", "F013", "F012", "F011", "F010", "F01")
> 
> dementia <- apply(sapply(df[, -1], function(x) {x %in% dementia}), 1, any)
> 
> df[!dementia,]
     ID disease_code_1 disease_code_2 disease_code_3
1  1001           I802           A071           H250
2  1002           H356             NA             NA
4  1004           D235             NA           I802
5  1005           B178             NA             NA
8  1008           C761             NA             NA
11 1011           J679           A045           D352
> 

Edit:

Еще более элегантное решение благодаря @ Ronan Shah:

> df[apply(df[-1], 1, function(x) {!any(x %in% dementia)}),]
     ID disease_code_1 disease_code_2 disease_code_3
1  1001           I802           A071           H250
2  1002           H356             NA             NA
4  1004           D235             NA           I802
5  1005           B178             NA             NA
8  1008           C761             NA             NA
11 1011           J679           A045           D352

Надеюсь, это поможет.

2 голосов
/ 29 марта 2019

A for версия петли с base R, если вы предпочитаете это.

df <- data.frame(ID = c(1001, 1002, 1003, 1004, 1005,1006,1007,1008,1009,1010,1011),
                disease_code_1 = c('I802','H356','G560','D235','B178','F011','F023','C761','H653','A049','J679'),
                disease_code_2 = c('A071','NA','G20','NA','NA','A049','NA','NA','G300','G308','A045'),
                disease_code_3 = c('H250','NA','NA','I802','NA','A481','NA','NA','NA','NA','D352'), stringsAsFactors = FALSE)

dementia_codes <- c("F023", "G20", "F009", "F002", "F001", "F000", "F00", "G309", "G308", "G301", "G300", "G30", "F01", "F018", "F013", "F012", "F011", "F010", "F01")

new_df <- df[0,]

for(i in 1:nrow(df)){
  currRow <- df[i,]
  if(any(dementia_codes %in% as.character(currRow)) == FALSE){
    new_df <- rbind(new_df, currRow)
  }
}

new_df
#      ID disease_code_1 disease_code_2 disease_code_3
# 1  1001           I802           A071           H250
# 2  1002           H356             NA             NA
# 4  1004           D235             NA           I802
# 5  1005           B178             NA             NA
# 8  1008           C761             NA             NA
# 11 1011           J679           A045           D352
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...