使用for循环进行数据清理

时间:2019-08-31 19:38:05

标签: r

我正在重组包含血压读数的变量。每个读数均包含收缩期和舒张期值,并用正斜杠(/)分隔。对于此示例,每行(即每人)有三个读数。

我想要的输出是为每个读数的收缩压和舒张压值分别设置变量。

这是csv的数据示例:

id,v1,v2,v3  
1,116 / 77,121 / 68,105 / 76  
2,164 / 67,171 / 79,155 / 68  
3,146 / 109,,  
4,120 / 80,102 / 64,137 / 87   
5,112 / 50,130 / 40,  

在加载tidyverse之后,我可以针对每个读数(例如,

)分别使用
blPr <- read_csv('BlPr.csv')  
blPr <- blPr %>% separate (v1 , c('v1_sys' , 'v1_dias') , sep = '/' , remove = FALSE) 

但是,由于实际数据集的人均读数更多,因此我试图通过使用for循环来消除多行。在查看了网上的一些示例后,我尝试了:

for (i in 1:3) {  
  blPr <- blPr %>% separate (v[i] , c('v[i]_sys' , 'v[i]_dias') , sep = '/' ,   remove = FALSE)  
}  

它返回了错误消息:

Error in eval_tidy(enquo(var), var_env) : object 'v' not found

我已经以几种方式修改了代码,但是由于我不了解问题所在,所以我空了。

3 个答案:

答案 0 :(得分:1)

我看到有人的答案刚刚被接受,但无论如何都会发布我的答案。如果要以最小的方式更改代码,可以采用以下方法:

for (i in 1:3) {
  blPr <- blPr %>% 
    separate(paste0('v', i), c(paste0('v', i, '_sys'), paste0('v', i, '_dias')), sep = ' / ', remove = F)
}

简短的解释(希望)可以帮助您理解代码为何无效的原因: 您可以使用未加引号的变量(即列)名称作为tidyverse参数,但它们不是参照透明的。这意味着您的代码正在v中寻找名为blPr literally 列,显然找不到该列。有时,尽管据我所知并非总是如此,tidyverse动词(例如separate)接受带有列名称的字符串来表示这些列-我在上面的代码中使用的功能(请注意,'v'是一个串)。有关更多信息,您可以阅读整洁的评估,准报价等内容。

答案 1 :(得分:0)

下面的代码有效...

# Create dataframe
blPr = read.table(text = '
id,v1,v2,v3  
1,116 / 77,121 / 68,105 / 76  
2,164 / 67,171 / 79,155 / 68  
3,146 / 109,,
4,120 / 80,102 / 64,137 / 87   
5,112 / 50,130 / 40,
', header = T, sep = ",")

library(tidyr)

for (i in c(1:3)){
eval(parse(text=paste0(  
"blPr <- blPr %>% separate (v",i," , c('v",i,"_sys' , 'v",i,"_dias') , sep = '/' , remove = FALSE)"
)))
}

答案 2 :(得分:0)

您可以做的就是保留所有读数,并将数据放入整洁的格式中:

result <- data %>%
    gather("reading", "value", -id) %>%
    mutate(value = trimws(value),
           value = ifelse(value == "", NA_character_, value)) %>%
    arrange(id, reading) %>%
    separate(value, c("systolic", "diastolic"), "/", convert = TRUE)


> head(result)
   id reading systolic diastolic
1   1      v1      116        77
2   1      v2      121        68
3   1      v3      105        76
4   2      v1      164        67
5   2      v2      171        79
6   2      v3      155        68

您可以更进一步,a)删除NA,b)放入长格式:

result_long <- result %>%
    filter(complete.cases(.)) %>%
    gather("reading_type", "value", -id, -reading) %>% 


> head(result_long)
   id reading reading_type value
1   1      v1     systolic   116
2   1      v2     systolic   121
3   1      v3     systolic   105
4   2      v1     systolic   164
5   2      v2     systolic   171
6   2      v3     systolic   155

整齐的格式使缠绕和绘制数据变得非常容易。将它们重新设置为易于阅读的形式也非常容易。在result中选择的格式可能是人类可读和易于处理之间的良好折衷。

绘图

library(ggplot)

ggplot(result_long) + 
    geom_point(aes(reading, value, color = reading_type, group = reading_type)) +
    geom_line(aes(reading, value, color = reading_type, group = reading_type)) +
    facet_wrap(id ~ .)

1

将数据放入广泛的格式

result_wide <- result_long %>% 
    spread("reading_type", "value", drop = TRUE) %>%
    unite("value", c("systolic", "diastolic"), sep = " / ") %>%
    spread("reading", "value")


> result_wide
  id        v1       v2       v3
1  1  116 / 77 121 / 68 105 / 76
2  2  164 / 67 171 / 79 155 / 68
3  3 146 / 109     <NA>     <NA>
4  4  120 / 80 102 / 64 137 / 87
5  5  112 / 50 130 / 40     <NA>

数据

library(tidyverse)

data <- read.table(text = '
id,v1,v2,v3  
1,116 / 77,121 / 68,105 / 76  
2,164 / 67,171 / 79,155 / 68  
3,146 / 109,,
4,120 / 80,102 / 64,137 / 87   
5,112 / 50,130 / 40,
', header = T, sep = ",")