这是我的数据的链接.
我的目标是为所有空白单元分配"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
Run Code Online (Sandbox Code Playgroud)
Bad*_*doe 86
我假设你在谈论第5行"性".可能是这样的情况:在data2.csv文件中,单元格包含一个空格,因此不被R视为空.
另外,我注意到在第5行"axles"和"door"中,从data2.csv读取的原始值是字符串"NA".您可能也希望将它们视为na.strings.去做这个,
dat2 <- read.csv("data2.csv", header=T, na.strings=c("","NA"))
Run Code Online (Sandbox Code Playgroud)
编辑:
我下载了你的data2.csv.是的,第5行"性别"中有一个空格.所以你要
na.strings=c(""," ","NA")
Run Code Online (Sandbox Code Playgroud)
小智 30
您可以使用gsub将空的多个突变(如""或空格)替换为NA:
data= data.frame(cats=c('', ' ', 'meow'), dogs=c("woof", " ", NA))
apply(data, 2, function(x) gsub("^$|^ $", NA, x))
Run Code Online (Sandbox Code Playgroud)
Hol*_*ndl 21
采用了更为眼睛友好的解决方案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))
Run Code Online (Sandbox Code Playgroud)
要将更正应用于列的子集,您可以使用dplyr的列匹配语法指定感兴趣的列.例:mutate_each(funs(empty_as_na), matches("Width"), Species)
如果您的表包含日期,您应该考虑使用更安全的版本ifelse
小智 12
我最近遇到了类似的问题.这对我有用,如果变量是数字,那么简单df$Var[df$Var == ""] <- "NA"就足够了.但是如果变量是一个因子,那么你需要先将它转换为字符,然后用""你想要的值替换单元格,然后将其转换回因子.举个例子,你的性别变量,我认为这将是一个因素,如果你想要替换空单元格,我会做以下事情:
df$Var <- as.character(df$Var)
df$Var[df$Var==""] <- "NA"
df$Var <- as.factor(df$Var)
Run Code Online (Sandbox Code Playgroud)
gle*_*ton 12
更新的答案 我发现一些额外的选项很有用,它们建立在 @camnesia 利用 dplyr 的 across() 的出色选项的基础上:
使用 na_if()
mutate(across(c("Age","Gender"), ~na_if(., "")))。
对于那些闲逛的人来说,也许值得注意的是,除了用 c("") 指定列之外,您还可以使用 dplyr 选择器:
mutate(across(starts_with("x_"), ~na_if(., "")))。
最后,如果您想用 NA 替换多个值,我也喜欢这里的 Replace() :
使用替换():
mutate(across(everything(), ~replace(., . %in% c("N.A.", "NA", "N/A", ""), NA)))
原始答案 我怀疑每个人都已经有了答案,尽管万一有人来寻找, dplyr na_if() (从我的角度来看)将是所提到的更有效的:
# Import CSV, convert all 'blank' cells to NA
dat <- read.csv("data2.csv") %>% na_if("")
Run Code Online (Sandbox Code Playgroud)
这是利用 readr 的 read_delim 函数的另一种方法。我刚刚拿起(可能广为人知,但我将在这里存档以供将来的用户使用)。这非常简单,比上面的更通用,因为您可以在 csv 文件中捕获所有类型的空白和 NA 相关值:
dat <- read_csv("data2.csv", na = c("", "NA", "N/A"))
Run Code Online (Sandbox Code Playgroud)
请注意 readr 版本中的下划线与 Base R“.” 在 read_csv.
希望这对那些在帖子中徘徊的人有所帮助!
从(dplyr 1.0.0)我们可以使用across()
注意:有时NA在变量中使用会导致问题,您可能需要指定类型NA- 例如对于这种情况,它是NA_character_. 对于嵌套ifelse()语句,您可以使用case_when().
对于所有列:
dat <- dat %>%
mutate(across(everything(), ~ifelse(.=="", NA, as.character(.))))
Run Code Online (Sandbox Code Playgroud)
对于单个列:
dat <- dat %>%
mutate(across(c("Age","Gender"), ~ifelse(.=="", NA, as.character(.))))
Run Code Online (Sandbox Code Playgroud)
从(上面的dplyr 0.8.0)开始,应该写的方式已经改变。在此之前,funs()在.funs (funs(name = f(.)). 而不是funs,现在我们使用list (list(name = ~f(.)))
请注意,还有一种更简单的方法可以列出列名!(列名和列索引都有效)
dat <- dat %>%
mutate_at(.vars = c("Age","Gender"),
.funs = list(~ifelse(.=="", NA, as.character(.))))
Run Code Online (Sandbox Code Playgroud)
原答案:
您也可以mutate_at在dplyr
dat <- dat %>%
mutate_at(vars(colnames(.)),
.funs = funs(ifelse(.=="", NA, as.character(.))))
Run Code Online (Sandbox Code Playgroud)
选择要更改的单个列:
dat <- dat %>%
mutate_at(vars(colnames(.)[names(.) %in% c("Age","Gender")]),
.funs = funs(ifelse(.=="", NA, as.character(.))))
Run Code Online (Sandbox Code Playgroud)
我认为这是你最好的选择(为了代码简单和速度)。以下代码将用 NA 替换名为“data”的数据集中的所有空白:
data[data==""] <- NA
Run Code Online (Sandbox Code Playgroud)
如果您使用 Haven 或foreign 包来读取外部文件,我的函数会考虑因子、字符向量和潜在属性。它还允许匹配不同的自定义 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)
}
Run Code Online (Sandbox Code Playgroud)