将字符串分成不同的列 R

问题描述 投票:0回答:1

我有一份问卷调查的数据,其中一个问题是多选题,包括 "其他 "选项,用户可以写一些其他的东西。其中一个问题是多选题,包括 "其他 "这个选项,用户可以写其他的东西。我收到了一个Excel文件,其中有一列关于该特定问题的内容,每个选项都用分号隔开。下面是数据集的例子。

ID  Prob_saude
1   "Não tenho nenhum dos problemas de saúde indicados;" 
2   " Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);"
3   " Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);Hipertensão arterial (tensão arterial alta);Problemas renais crónicos (doença nos rins, incluindo insuficiência renal);"
4   "Doença autoimmune;" 
5   " Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);Hipertensão arterial (tensão arterial alta);Diabetes;"  
6    "HIV;"
7    "Não tenho nenhum dos problemas de saúde indicados;" 
8    "Cardiológica;" 

我想为每一种疾病创建一列 "yesno",以防用户选择该选项。然后,我想为另一列创建一个选项为other的列。在这种情况下,可用的选项是。

disease <- c(" Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);",
         "Hipertensão arterial (tensão arterial alta);", "Doença autoimmune;"
         "Problemas renais crónicos (doença nos rins, incluindo insuficiência renal);",
         "Não tenho nenhum dos problemas de saúde indicados;") 

我希望的输出是这样的

ID  Prob_saude_1 Prob_saude_2 Prob_saude_3 Prob_saude_4 Prob_saude_5 Prob_saude_6 Prob_saude
1         1           1            1            1            2          NA        "Não tenho nenhum dos problemas de saúde indicados;" 
2         2           1            1            1            1          NA        " Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);"
3         2           2            1            2            1          NA        " Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);Hipertensão arterial (tensão arterial alta);Problemas renais crónicos (doença nos rins, incluindo insuficiência renal);"
4        1           1            2            1            1          NA        "Doença autoimmune;" 
5        2           2            1            1            1        "Diabetes;" " Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);Hipertensão arterial (tensão arterial alta);Diabetes;"  
6        1           1            1            1            1          "HIV;"      "HIV;"
7        1           1            1            1            2          NA           "Não tenho nenhum dos problemas de saúde indicados;" 
8        1           1            1            1            1       "Cardiológica;" "Cardiológica;" 

我可以根据选项创建额外的列 但当我尝试创建其他的列时 输出的结果等于Prob_saude列 所以它不排除已经选择的选项 有什么想法吗?这是我目前的情况。如果你认为有更好的方法可以实现,欢迎提出任何建议。

dataset[, paste("Prob_saude", length(disease)+1, sep = "_") := Prob_saude]

for (index in 1:length(disease)) {
    rows <- grep(disease[index], dataset$Prob_saude, fixed = T)
    dataset[, paste("Prob_saude", index, sep = "_") := ifelse(rownames(dataset) %in% rows, 2, ifelse(is.na(dataset$Prob_saude), NA, 1))]
    dataset[, paste("Prob_saude", length(disease)+1, sep = "_") := gsub(disease[index], "", dataset$Prob_saude, fixed = T)]
}
r gsub
1个回答
1
投票

处理这种情况的一种方法是将疾病类型列表中列出的 "其他 "项目合并。给定数据,原来有5个病种,在原 disease 向量,以及问卷中的三个新的。

首先,经过一些清理,我们读取问题发布的数据。

textFile <- "id|response
1|Não tenho nenhum dos problemas de saúde indicados; 
2| Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);
3| Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);Hipertensão arterial (tensão arterial alta);Problemas renais crónicos (doença nos rins, incluindo insuficiência renal);
4|Doença autoimmune; 
5| Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica);Hipertensão arterial (tensão arterial alta);Diabetes;  
6|HIV;
7|Não tenho nenhum dos problemas de saúde indicados; 
8|Cardiológica; "

data <- read.csv(text = textFile,sep = "|",
                 header = TRUE, stringsAsFactors = FALSE)
disease <- c("Doença respiratória/pulmonar (incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica)",
             "Hipertensão arterial (tensão arterial alta)", 
             "Doença autoimmune",
             "Problemas renais crónicos (doença nos rins, incluindo insuficiência renal)",
             "Não tenho nenhum dos problemas de saúde indicados")

接下来,我们从tidyverse中加载一些包,对问卷数据进行清理,并将其转换为窄格式的tidy数据。

library(tidyr)
library(dplyr)
library(glue)
data %>% separate(.,response,into = c("resp1","resp2","resp3","resp4","resp5"),
                  sep=";")  %>% group_by(id) %>%
     pivot_longer(.,c(resp1,resp2,resp3,resp4,resp5),values_to = "disease") %>%
     mutate(disease = trimws(disease)) %>%
     filter(!disease %in% c(NA," ","  ",""))    -> narrowData

这时 narrowData 包含12个观测值和3列。

> head(narrowData)
# A tibble: 6 x 3
# Groups:   id [4]
     id name  disease                                                             
  <int> <chr> <chr>                                                               
1     1 resp1 Não tenho nenhum dos problemas de saúde indicados                   
2     2 resp1 Doença respiratória/pulmonar (incluindo asma, bronquite crónica e d…
3     3 resp1 Doença respiratória/pulmonar (incluindo asma, bronquite crónica e d…
4     3 resp2 Hipertensão arterial (tensão arterial alta)                         
5     3 resp3 Problemas renais crónicos (doença nos rins, incluindo insuficiência…
6     4 resp1 Doença autoimmune                                                   
> 

接下来,我们结合来自 disease 向量,以找到调查和输入疾病列表中的唯一值。

narrowData %>% distinct(trimws(disease)) %>% .[[1]] -> diseaseList
# expanded list
combinedDiseases <- unique(c(diseaseList,disease))
disease_id <- 1:length(combinedDiseases)
diseaseData <- data.frame(disease_id,disease = combinedDiseases,
                          stringsAsFactors = FALSE)

diseaseData 数据框架看起来像这样,其中在问卷中报告但不在原始列表中的疾病位于第 6、7 和 8 位。

enter image description here

由于我们创建了一个唯一的序列号与每个疾病名称相关联,现在我们可以合并数据,并使用疾病id号将数据按调查对象id转回宽格式数据集。

narrowData %>% left_join(.,diseaseData) -> joinedData
# create wide format data 
joinedData %>% select(id,disease_id) %>% mutate(value = 2) %>%
     pivot_wider(.,id_cols = id,names_from = disease_id,names_prefix = "disease",
                 values_from = value) -> result

最后,我们将输出中的所有NA值设置为1,并打印。

result[is.na(result)] <- 1
result

.并输出。

> result
# A tibble: 8 x 9
# Groups:   id [8]
     id disease1 disease2 disease3 disease4 disease5 disease6 disease7 disease8
  <int>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
1     1        2        1        1        1        1        1        1        1
2     2        1        2        1        1        1        1        1        1
3     3        1        2        2        2        1        1        1        1
4     4        1        1        1        1        2        1        1        1
5     5        1        2        2        1        1        2        1        1
6     6        1        1        1        1        1        1        2        1
7     7        2        1        1        1        1        1        1        1
8     8        1        1        1        1        1        1        1        2
> 

将额外报告的疾病编码为 "其他"

根据对我的回答的评论,上级希望调查对象报告的任何疾病,如果不在最初的疾病列表中,则将其编码为一个单一的响应变量。这里的代码可以满足这个要求。

library(tidyr)
library(dplyr)
library(glue)
data %>% separate(.,response,into = c("resp1","resp2","resp3","resp4","resp5"),
                  sep=";")  %>% group_by(id) %>%
     pivot_longer(.,c(resp1,resp2,resp3,resp4,resp5),values_to = "disease") %>%
     mutate(disease = trimws(disease)) %>%
     filter(!disease %in% c(NA," ","  ",""))    -> narrowData

再次,我们有一个窄格式整齐的数据框架,由每一种报告的疾病的一行组成。

接下来,我们对疾病进行处理,找出不在原选择列表中的报告疾病,给它们分配一个大于长度的疾病id。disease 向量,并创建一个数据框架。

# create disease data frame by combining data with unique values in survey data frame
narrowData %>% distinct(trimws(disease)) %>% .[[1]] -> reportedDiseases
notInDiseaseList <- unique(reportedDiseases[!reportedDiseases %in% disease ])
disease_id <- 1:length(disease)
diseaseData <- data.frame(disease_id,disease,stringsAsFactors = FALSE)
disease_id <- rep(max(diseaseData$disease_id)+1,length(notInDiseaseList))
reportedDiseases <- data.frame(disease_id,disease = notInDiseaseList,stringsAsFactors = FALSE)
diseaseData <- rbind(diseaseData,reportedDiseases)

请注意,原始列表中没有的报告疾病都有相同的值,即 disease_id.

enter image description here

接下来,我们加入 diseaseData 数据帧与窄格式文件,所以我们可以 pivot_wider() 由疾病id。

narrowData %>% left_join(.,diseaseData) -> joinedData

最后,我们剔除重复的 disease_id 等于6,然后再使用`pivot_wider()创建一个数据框,其中有6列1=无病,2=5种类型的疾病加 "其他"。

# create wide format data after eliminating 
# any duplicates where multiple reported diseases for a respondent
joinedData %>% select(id,disease_id) %>% 
     group_by(id,disease_id) %>%
     mutate(value = 2, n = row_number()) %>%
     filter(n == 1) %>% 
     pivot_wider(.,id_cols = id,names_from = disease_id,names_prefix = "disease",
                 values_from = value) -> result
result[is.na(result)] <- 1
result

....还有输出。

> result
# A tibble: 8 x 7
# Groups:   id [8]
     id disease5 disease1 disease2 disease4 disease3 disease6
  <int>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
1     1        2        1        1        1        1        1
2     2        1        2        1        1        1        1
3     3        1        2        2        2        1        1
4     4        1        1        1        1        2        1
5     5        1        2        2        1        1        2
6     6        1        1        1        1        1        2
7     7        2        1        1        1        1        1
8     8        1        1        1        1        1        2
> 

0
投票

gsub 由于括号的原因而无法工作。改变字符串解决了这个问题。

现在的代码有点长。

 dataset[, paste("Prob_saude", length(disease)+1, sep = "_") := Prob_saude]
for (index in 1:length(disease)) {
    rows <- grep(disease[index], dataset$Prob_saude, fixed = T)
    dataset[, paste("Prob_saude", index, sep = "_") := ifelse(rownames(dataset) %in% rows, 2, ifelse(is.na(dataset$Prob_saude), NA, 1))]
}

disease <- c(" Doença respiratória/pulmonar \\(incluindo asma, bronquite crónica e doença pulmonar obstrutiva crónica\\);|Hipertensão arterial \\(tensão arterial alta\\);|Doença autoimmune;|Problemas renais crónicos \\(doença nos rins, incluindo insuficiência renal\\);Não tenho nenhum dos problemas de saúde indicados;") 
dataset$other_disease <- gsub(disease, "", dataset$Prob_saude)
© www.soinside.com 2019 - 2024. All rights reserved.