R:汇总多列(数字,字符)并删除 NA
R: summarise multiple column (numeric, character) and remove NAs
我有一个包含很多列 (~50) 的 data.frame。其中一些是字符,一些是数字,其中 3 个用于分组。
我需要:
- 从数字列中删除 NA
- 计算每个数字列的平均值
- 提取字符列的第一个元素
比方说,我们使用修改后的虹膜数据如下:
data(iris)
iris$year <- rep(c(2000,3000),each=25) ## for grouping
iris$color <- rep(c("red","green","blue"),each=50) ## character column
iris[1,] <- NA ## introducing NAs
我总共有大约 50 列,数字和字符混合在一起。我一直在尝试类似的东西:
giris <- group_by(iris, Species, year)
cls <- unlist(sapply(giris, class)) ## find out classes
action <- ifelse(cls == "numeric", "mean", "first")
action <- paste(action)
summarise_each(giris, action)
我得到的是组中所有列的意思,后跟各组中具有第一个值的列。而且 NA 没有得到处理...这不是我想要的...
有人帮忙吗?
您可以在 summarise_each
的 funs
中使用 if
/else
进行尝试:
iris %>%
group_by(Species, year) %>%
summarise_each(funs(if(is.numeric(.)) mean(., na.rm = TRUE) else first(.)))
由于您在分组列中也有一些 NA,因此您可以添加 filter
语句:
iris %>%
filter(!is.na(Species) & !is.na(year)) %>%
group_by(Species, year) %>%
summarise_each(funs(if(is.numeric(.)) mean(., na.rm = TRUE) else first(.)))
#Source: local data frame [6 x 7]
#Groups: Species [?]
#
# Species year Sepal.Length Sepal.Width Petal.Length Petal.Width color
# (fctr) (dbl) (dbl) (dbl) (dbl) (dbl) (chr)
#1 setosa 2000 5.025 3.479167 1.4625 0.250 red
#2 setosa 3000 4.984 3.376000 1.4640 0.244 red
#3 versicolor 2000 6.012 2.776000 4.3120 1.344 green
#4 versicolor 3000 5.860 2.764000 4.2080 1.308 green
#5 virginica 2000 6.576 2.928000 5.6400 2.044 blue
#6 virginica 3000 6.600 3.020000 5.4640 2.008 blue
为避免颜色列(或任何 non-numeric 列)中出现潜在的 NA,您可以将其修改为 first(na.omit(.))
。
您也可以尝试 data.table
:
library(data.table)
setDT(iris)
iris[!is.na(Species) & !is.na(year), lapply(.SD, function(x) {
if(is.numeric(x)) mean(x, na.rm = TRUE) else x[!is.na(x)][1L]}),
by = list(Species, year)]
# Species year Sepal.Length Sepal.Width Petal.Length Petal.Width color
#1: setosa 2000 5.025 3.479167 1.4625 0.250 red
#2: setosa 3000 4.984 3.376000 1.4640 0.244 red
#3: versicolor 2000 6.012 2.776000 4.3120 1.344 green
#4: versicolor 3000 5.860 2.764000 4.2080 1.308 green
#5: virginica 2000 6.576 2.928000 5.6400 2.044 blue
#6: virginica 3000 6.600 3.020000 5.4640 2.008 blue
我试一试:
1。
对于你提到的第一点,我会做类似以下的事情(第二点不是必需的):
na.omit(iris[ , which(sapply(iris, class) == "numeric")])
要将列分隔为 numeric
或 character
,我使用以下内容:
iris[ , which(sapply(iris, class) == "numeric")]
iris[ , which(sapply(iris, class) == "character")]
2。
第二个任务我将上面的行与 colMeans
:
结合起来
colMeans(iris[ , which(sapply(iris, class) == "numeric")], na.rm = TRUE)
3。
要提取字符列的第一个元素,您可以简单地执行:
iris[1, which(sapply(iris, class) == "character")]
在提到的 iris 数据的情况下,第一行完全是 NA,甚至是字符列,所以我会迭代以找到 first-non-NA-row
k <- 1
while(any(is.na(FirstCharacterElement <- iris[k, which(sapply(iris, class) == "character")]))){
k <- k + 1
}
注意 class 因素(在 iris 数据的情况下,它会破坏代码,其中列 Species 是 class 因素,您可能希望它是一个字符列。您可以使用 sapply(iris, class)
检查并使用例如
进行更改
iris$Species <- as.character(iris$Species) #or with similar column names
当您读入数据时,您可以提及函数 read.table
、read.csv
或类似函数的参数 stringsAsFactors = FALSE
。
我有一个包含很多列 (~50) 的 data.frame。其中一些是字符,一些是数字,其中 3 个用于分组。
我需要:
- 从数字列中删除 NA
- 计算每个数字列的平均值
- 提取字符列的第一个元素
比方说,我们使用修改后的虹膜数据如下:
data(iris)
iris$year <- rep(c(2000,3000),each=25) ## for grouping
iris$color <- rep(c("red","green","blue"),each=50) ## character column
iris[1,] <- NA ## introducing NAs
我总共有大约 50 列,数字和字符混合在一起。我一直在尝试类似的东西:
giris <- group_by(iris, Species, year)
cls <- unlist(sapply(giris, class)) ## find out classes
action <- ifelse(cls == "numeric", "mean", "first")
action <- paste(action)
summarise_each(giris, action)
我得到的是组中所有列的意思,后跟各组中具有第一个值的列。而且 NA 没有得到处理...这不是我想要的...
有人帮忙吗?
您可以在 summarise_each
的 funs
中使用 if
/else
进行尝试:
iris %>%
group_by(Species, year) %>%
summarise_each(funs(if(is.numeric(.)) mean(., na.rm = TRUE) else first(.)))
由于您在分组列中也有一些 NA,因此您可以添加 filter
语句:
iris %>%
filter(!is.na(Species) & !is.na(year)) %>%
group_by(Species, year) %>%
summarise_each(funs(if(is.numeric(.)) mean(., na.rm = TRUE) else first(.)))
#Source: local data frame [6 x 7]
#Groups: Species [?]
#
# Species year Sepal.Length Sepal.Width Petal.Length Petal.Width color
# (fctr) (dbl) (dbl) (dbl) (dbl) (dbl) (chr)
#1 setosa 2000 5.025 3.479167 1.4625 0.250 red
#2 setosa 3000 4.984 3.376000 1.4640 0.244 red
#3 versicolor 2000 6.012 2.776000 4.3120 1.344 green
#4 versicolor 3000 5.860 2.764000 4.2080 1.308 green
#5 virginica 2000 6.576 2.928000 5.6400 2.044 blue
#6 virginica 3000 6.600 3.020000 5.4640 2.008 blue
为避免颜色列(或任何 non-numeric 列)中出现潜在的 NA,您可以将其修改为 first(na.omit(.))
。
您也可以尝试 data.table
:
library(data.table)
setDT(iris)
iris[!is.na(Species) & !is.na(year), lapply(.SD, function(x) {
if(is.numeric(x)) mean(x, na.rm = TRUE) else x[!is.na(x)][1L]}),
by = list(Species, year)]
# Species year Sepal.Length Sepal.Width Petal.Length Petal.Width color
#1: setosa 2000 5.025 3.479167 1.4625 0.250 red
#2: setosa 3000 4.984 3.376000 1.4640 0.244 red
#3: versicolor 2000 6.012 2.776000 4.3120 1.344 green
#4: versicolor 3000 5.860 2.764000 4.2080 1.308 green
#5: virginica 2000 6.576 2.928000 5.6400 2.044 blue
#6: virginica 3000 6.600 3.020000 5.4640 2.008 blue
我试一试:
1。 对于你提到的第一点,我会做类似以下的事情(第二点不是必需的):
na.omit(iris[ , which(sapply(iris, class) == "numeric")])
要将列分隔为 numeric
或 character
,我使用以下内容:
iris[ , which(sapply(iris, class) == "numeric")]
iris[ , which(sapply(iris, class) == "character")]
2。
第二个任务我将上面的行与 colMeans
:
colMeans(iris[ , which(sapply(iris, class) == "numeric")], na.rm = TRUE)
3。 要提取字符列的第一个元素,您可以简单地执行:
iris[1, which(sapply(iris, class) == "character")]
在提到的 iris 数据的情况下,第一行完全是 NA,甚至是字符列,所以我会迭代以找到 first-non-NA-row
k <- 1
while(any(is.na(FirstCharacterElement <- iris[k, which(sapply(iris, class) == "character")]))){
k <- k + 1
}
注意 class 因素(在 iris 数据的情况下,它会破坏代码,其中列 Species 是 class 因素,您可能希望它是一个字符列。您可以使用 sapply(iris, class)
检查并使用例如
iris$Species <- as.character(iris$Species) #or with similar column names
当您读入数据时,您可以提及函数 read.table
、read.csv
或类似函数的参数 stringsAsFactors = FALSE
。