这是一个关于最佳实践的一般问题。
我使用tidyverse包从CSV导入、读取并操作临床实验室数据。对于临床数据,通常用"小于"或"大于"符号报告量化极限之外的值,例如<250 mg/dL或>2500 mg/dL。因此,您通常会有一个列,其中大部分是数值,但也有一些值会被readr解释为字符串。如果我强制该列为数字,那么默认情况下,字符串被强制为NA。
我希望能够告诉readr或dplyr接受那些字符串值(例如<250,>2500(作为数值,去掉字符(例如2502500(。理想情况下,这将在管道中完成
一般来说,处理这种情况最灵活、最一致的方法是什么?
信任其中一个包来了解"<250 mg/dL"
的含义超出了他们的专业领域。例如,根据您的需要,该值可能意味着"有效0">或"有效250">或者其他什么。无论这是否适用于药物、抗体、化学物质或其他什么,它都是绝对上下文相关的。
鉴于此,我认为程序员/分析师有责任确定什么是合适的。
基本R方法,假设2:3
反映了需要修复的列:
dat <- read.csv(text = csv, stringsAsFactors = FALSE)
str(dat)
# 'data.frame': 2 obs. of 3 variables:
# $ id : int 1 2
# $ val1: chr "<250 mg/dL" ">250 mg/dL"
# $ val2: chr ">2500 mg/dL" "<2500 mg/dL"
dat[,2:3] <- lapply(dat[,2:3], function(s) as.numeric(gsub("[^-.0-9]", "", s)))
str(dat)
# 'data.frame': 2 obs. of 3 variables:
# $ id : int 1 2
# $ val1: num 250 250
# $ val2: num 2500 2500
一个小版本:
library(dplyr)
readr::read_csv(csv) %>%
mutate_at(vars(val1, val2), ~ as.numeric(stringr::str_replace_all(., "[^-.0-9]", "")))
data.table
也很容易适应上面的lapply
。
然而,这只是假设<250
与250
相同,这并没有区分"真实"值和"小于"值。考虑:
csv <-'
id,val1,val2
1,"<250 mg/dL",">2500 mg/dL"
2,">250 mg/dL","<2500 mg/dL"
3,25,2500'
第3行应如何区别于其他行?为此,我认为你需要融入更多的逻辑,也许是ifelse(grepl("<", s), "0", s)
等。同样,这都是上下文相关的,所以只有分析师知道解释这些数字时应该遵循什么规则。