以下是我的数据link。
我的目标是为所有空白单元分配“NA”,而不管分类或数值。我正在使用 na.strings =“”。但它没有为所有空白细胞分配NA。
## reading the data
dat <- read.csv("data2.csv")
head(dat)
mon hr acc alc sex spd axles door reg cond1 drug1
1 8 21 No Control TRUE F 0 2 2 Physical Impairment (Eyes, Ear, Limb) A
2 7 20 No Control FALSE M 900 2 2 Inattentive D
3 3 9 No Control FALSE F 100 2 2 2004 Normal D
4 1 15 No Control FALSE M 0 2 2 Physical Impairment (Eyes, Ear, Limb) D
5 4 21 No Control FALSE 25 NA NA D
6 4 20 No Control NA F 30 2 4 Drinking Alcohol - Impaired D
inj1 PED_STATE st rac1
1 Fatal <NA> F <NA>
2 Moderate <NA> F <NA>
3 Moderate <NA> M <NA>
4 Complaint <NA> M <NA>
5 Complaint <NA> F <NA>
6 Moderate <NA> M <NA>
## using na.strings
dat2 <- read.csv("data2.csv", header=T, na.strings="")
head(dat2)
mon hr acc alc sex spd axles door reg cond1 drug1
1 8 21 No Control TRUE F 0 2 2 <NA> Physical Impairment (Eyes, Ear, Limb) A
2 7 20 No Control FALSE M 900 2 2 <NA> Inattentive D
3 3 9 No Control FALSE F 100 2 2 2004 Normal D
4 1 15 No Control FALSE M 0 2 2 <NA> Physical Impairment (Eyes, Ear, Limb) D
5 4 21 No Control FALSE 25 NA NA <NA> <NA> D
6 4 20 No Control NA F 30 2 4 <NA> Drinking Alcohol - Impaired D
inj1 PED_STATE st rac1
1 Fatal NA F NA
2 Moderate NA F NA
3 Moderate NA M NA
4 Complaint NA M NA
5 Complaint NA F NA
6 Moderate NA M NA
答案 0 :(得分:82)
我假设您正在谈论第5行&#34;性别。&#34;可能是在data2.csv文件中,单元格包含空格,因此R不会将其视为空。
另外,我注意到在第5行&#34;车轴&#34;和&#34;门&#34;,从data2.csv读取的原始值是字符串&#34; NA&#34;。您可能也希望将它们视为na.strings。为此,
dat2 <- read.csv("data2.csv", header=T, na.strings=c("","NA"))
编辑:
我下载了你的data2.csv。是的,第5行中有一个空格&#34; sex&#34;。所以你想要
na.strings=c(""," ","NA")
答案 1 :(得分:29)
您可以使用gsub将空的多个突变(如“”或空格)替换为NA:
data= data.frame(cats=c('', ' ', 'meow'), dogs=c("woof", " ", NA))
apply(data, 2, function(x) gsub("^$|^ $", NA, x))
答案 2 :(得分:18)
使用WITH ORDINALITY
的更友好的解决方案是
dplyr
要将更正应用于列的子集,您可以使用dplyr的列匹配语法指定感兴趣的列。例如:require(dplyr)
## fake blank cells
iris[1,1]=""
## define a helper function
empty_as_na <- function(x){
if("factor" %in% class(x)) x <- as.character(x) ## since ifelse wont work with factors
ifelse(as.character(x)!="", x, NA)
}
## transform all columns
iris %>% mutate_each(funs(empty_as_na))
如果您的表格包含日期,则应考虑使用mutate_each(funs(empty_as_na), matches("Width"), Species)
版本的ifelse
答案 3 :(得分:8)
我最近遇到了类似的问题。这对我有用,如果变量是数字,那么简单的df$Var[df$Var == ""] <- "NA"
就足够了。但是如果变量是一个因子,那么你需要先将它转换为字符,然后用你想要的值替换""
个单元格,然后将其转换回因子。举个例子,你的性别变量,我认为这将是一个因素,如果你想要替换空单元格,我会做以下事情:
df$Var <- as.character(df$Var)
df$Var[df$Var==""] <- "NA"
df$Var <- as.factor(df$Var)
答案 4 :(得分:3)
如果您使用避风港或外国包裹来读取外部文件,则我的功能会考虑因素,字符向量和潜在属性。它还允许匹配不同的自定义na.strings。要转换所有列,只需使用lappy:df[] = lapply(df, blank2na, na.strings=c('','NA','na','N/A','n/a','NaN','nan'))
查看更多评论:
#' Replaces blank-ish elements of a factor or character vector to NA
#' @description Replaces blank-ish elements of a factor or character vector to NA
#' @param x a vector of factor or character or any type
#' @param na.strings case sensitive strings that will be coverted to NA. The function will do a trimws(x,'both') before conversion. If NULL, do only trimws, no conversion to NA.
#' @return Returns a vector trimws (always for factor, character) and NA converted (if matching na.strings). Attributes will also be kept ('label','labels', 'value.labels').
#' @seealso \code{\link{ez.nan2na}}
#' @export
blank2na = function(x,na.strings=c('','.','NA','na','N/A','n/a','NaN','nan')) {
if (is.factor(x)) {
lab = attr(x, 'label', exact = T)
labs1 <- attr(x, 'labels', exact = T)
labs2 <- attr(x, 'value.labels', exact = T)
# trimws will convert factor to character
x = trimws(x,'both')
if (! is.null(lab)) lab = trimws(lab,'both')
if (! is.null(labs1)) labs1 = trimws(labs1,'both')
if (! is.null(labs2)) labs2 = trimws(labs2,'both')
if (!is.null(na.strings)) {
# convert to NA
x[x %in% na.strings] = NA
# also remember to remove na.strings from value labels
labs1 = labs1[! labs1 %in% na.strings]
labs2 = labs2[! labs2 %in% na.strings]
}
# the levels will be reset here
x = factor(x)
if (! is.null(lab)) attr(x, 'label') <- lab
if (! is.null(labs1)) attr(x, 'labels') <- labs1
if (! is.null(labs2)) attr(x, 'value.labels') <- labs2
} else if (is.character(x)) {
lab = attr(x, 'label', exact = T)
labs1 <- attr(x, 'labels', exact = T)
labs2 <- attr(x, 'value.labels', exact = T)
# trimws will convert factor to character
x = trimws(x,'both')
if (! is.null(lab)) lab = trimws(lab,'both')
if (! is.null(labs1)) labs1 = trimws(labs1,'both')
if (! is.null(labs2)) labs2 = trimws(labs2,'both')
if (!is.null(na.strings)) {
# convert to NA
x[x %in% na.strings] = NA
# also remember to remove na.strings from value labels
labs1 = labs1[! labs1 %in% na.strings]
labs2 = labs2[! labs2 %in% na.strings]
}
if (! is.null(lab)) attr(x, 'label') <- lab
if (! is.null(labs1)) attr(x, 'labels') <- labs1
if (! is.null(labs2)) attr(x, 'value.labels') <- labs2
} else {
x = x
}
return(x)
}
答案 5 :(得分:3)
这应该可以解决问题
dat <- dat %>% mutate_all(na_if,"")
答案 6 :(得分:2)
我怀疑每个人都已经有了答案,尽管万一有人来找,dplyr na_if()从我的角度来看将是提到的效率更高的
# Import CSV, convert all 'blank' cells to NA
dat <- read.csv("data2.csv") %>% na_if("")
这是利用阅读器的read_delim函数的另一种方法。我刚刚接了(可能广为人知,但我将在此处存档以供将来的用户使用)。这是非常简单的方法,比上面的方法更具通用性,因为您可以在csv文件中捕获所有类型的空白值和与NA相关的值:
dat <- read_csv("data2.csv", na = c("", "NA", "N/A"))
请注意,阅读器版本中的下划线与Base R“。在read_csv中。
希望这可以帮助那些徘徊在帖子上的人!
答案 7 :(得分:1)
尽管上面的许多选项都能很好地发挥作用,但我发现将非目标变量强制转换为chr
是有问题的。在ifelse
中使用grepl
和lapply
可解决这种脱靶效应(在有限测试中)。在grepl
中使用larky的正则表达式:
set.seed(42)
x1 <- sample(c("a","b"," ", "a a", NA), 10, TRUE)
x2 <- sample(c(rnorm(length(x1),0, 1), NA), length(x1), TRUE)
df <- data.frame(x1, x2, stringsAsFactors = FALSE)
强制角色类的问题:
df2 <- lapply(df, function(x) gsub("^$|^ $", NA, x))
lapply(df2, class)
$ x1
[1]“字符”
$ x2 [1]“字符”
使用ifelse的解决方案:
df3 <- lapply(df, function(x) ifelse(grepl("^$|^ $", x)==TRUE, NA, x))
lapply(df3, class)
$ x1
[1]“字符”
$ x2 [1]“数字”
答案 8 :(得分:1)
您还可以在mutate_at
中使用dplyr
dat <- dat %>%
mutate_at(vars(colnames(.)),
.funs = funs(ifelse(.=="", NA, as.character(.))))
选择要更改的各个列:
dat <- dat %>%
mutate_at(vars(colnames(.)[names(.) %in% c("Age","Gender")]),
.funs = funs(ifelse(.=="", NA, as.character(.))))
选择要跳过的各个列:
dat <- dat %>%
mutate_at(vars(colnames(.)[!names(.) %in% c("Birthday")]),
.funs = funs(ifelse(.=="", NA, as.character(.))))
答案 9 :(得分:1)
我认为 data.table 是您最好的选择(为了代码的简单性和速度)。以下将用 NA 替换名为“data”的数据集中的所有空白:
data[data==""] <- NA
答案 10 :(得分:0)
你不能使用
dat <- read.csv("data2.csv",na.strings=" ",header=TRUE)
应该在读入数据时将所有空白转换为NA 一定要在你的报价单之间留一个空格
答案 11 :(得分:0)
对于那些想了解使用 data.table 方法的解决方案的人,以下是我为其编写的函数,可在我的Github上使用:
library(devtools)
source_url("https://github.com/YoannPa/Miscellaneous/blob/master/datatable_pattern_substitution.R?raw=TRUE")
dt.sub(DT = dat2, pattern = "^$|^ $",replacement = NA)
dat2
该函数遍历每一列,以识别包含模式匹配项的列。然后,gsub()
仅加在包含模式"^$|^ $"
的匹配项的列上,以NA
s替换匹配项。
我将继续改进此功能以使其更快。
答案 12 :(得分:-2)
通过从{<1}}安装r
来调用dplyr
包
cran
它会将特定列中的所有空白单元格转换为NA
如果列包含&#34; - &#34;,&#34;&#34;,0这样根据空白单元格的类型在代码中更改
E.g。如果我得到像#34;&#34;而不是&#34; - &#34;,然后使用此代码:
library(dplyr)
(file)$(colname)<-sub("-",NA,file$colname)