聚合包含数字和字符串的列
aggregate a column that contains numbers and strings
我的 R 脚本中有一个数据框,看起来像这样:
ID B C
1539 Blue 8
1539 Blue 4
1539 Red 9
1539 Red 13
1539 Yellow NCAA
3574 Green RA
3574 Green RA
3574 Green RA
3574 Red 1
3574 Red 1
如何聚合列 C 并转换数据集,使其看起来像这样:
ID Blue Yellow Green Red
1539 12 NCAA - 22
3574 - - 3RA 2
我基本上想对数字求和并计算该值是否是 C 列中的一个因子。非常感谢任何帮助。
R 中的一列不能同时包含不同的 类,因此您实际上在 C
列中没有数字 - 它们要么是 characters
要么是 factors
。我们可能需要确保它们是 character
,这样我们才能对它们应用 type.convert
。此外,factor
s 有一个 integer
存储模式 - 所以它可能会让人困惑。之后,我们可以根据您的要求创建一个辅助函数,并将数据转换为宽格式。这是一个使用 data.table
的示例
library(data.table)
setDT(data1)[, C := as.character(C)] # Make sure it's a character column
# Define the function
f <- function(x) if(is.numeric(x <- type.convert(x))) {
as.character(sum(x))
} else paste0(length(x), x)
# Rehsape
dcast(data1, ID ~ B, value.var = "C", f)
# ID Blue Green Red Yellow
# 1: 1539 12 0 22 1NCAA
# 2: 3574 0 3RA 2 0
您使用 tidyr
和 dplyr
基本上使用两个步骤来执行此操作:
spread
( tidyr
) 创建新列,名称在 B
中,值在 C
中
group_by
您的 ID
列,然后 summarize_each
其余列 (dplyr
) 使用自定义汇总函数来处理字符或数字列
这是完整的解决方案,需要更多的命令来记账。
1.传播。传播的一个陷阱是所有行都必须在某些列中有一个唯一的 id(see here)
library(dplyr)
library(tidyr)
## spread with 'convert' will convert types automatically
spread_data <- dat %>%
mutate(row= 1:nrow(dat)) %>% ## uniquely id rows
spread(B, C, convert = TRUE) %>%
select(-row)
## converting the data.frame to a tbl_df
## lets us easily see the cols are different types
tbl_df(spread_data)
##Source: local data frame [10 x 5]
##
## ID Blue Green Red Yellow
## (int) (int) (chr) (int) (chr)
## 1 1539 8 NA NA NA
## 2 1539 4 NA NA NA
## 3 1539 NA NA 9 NA
## 4 1539 NA NA 13 NA
## 5 1539 NA NA NA NCAA
## 6 3574 NA RA NA NA
## 7 3574 NA RA NA NA
## 8 3574 NA RA NA NA
## 9 3574 NA NA 1 NA
## 10 3574 NA NA 1 NA
2.分组总结。首先,我们需要编写一个函数来处理任一类型的列
summarizer <- function(x) {
if (is.numeric(x)) {
sum(x, na.rm = TRUE)
} else {
# assume x is a character
if (all(is.na(x)))
return("-")
x[is.na(x)] <- ""
x <- unique(x)
paste0(x, collapse="")
}
}
## summarize each applies summarizer to the columns that aren't being used
## for grouping (so, not ID in this case)
spread_data %>% group_by(ID) %>%
summarize_each(funs(summarizer))
##Source: local data frame [2 x 5]
##
## ID Blue Green Red Yellow
## (int) (int) (chr) (int) (chr)
## 1 1539 12 - 22 NCAA
## 2 3574 0 RA 2 -
我的 R 脚本中有一个数据框,看起来像这样:
ID B C
1539 Blue 8
1539 Blue 4
1539 Red 9
1539 Red 13
1539 Yellow NCAA
3574 Green RA
3574 Green RA
3574 Green RA
3574 Red 1
3574 Red 1
如何聚合列 C 并转换数据集,使其看起来像这样:
ID Blue Yellow Green Red
1539 12 NCAA - 22
3574 - - 3RA 2
我基本上想对数字求和并计算该值是否是 C 列中的一个因子。非常感谢任何帮助。
R 中的一列不能同时包含不同的 类,因此您实际上在 C
列中没有数字 - 它们要么是 characters
要么是 factors
。我们可能需要确保它们是 character
,这样我们才能对它们应用 type.convert
。此外,factor
s 有一个 integer
存储模式 - 所以它可能会让人困惑。之后,我们可以根据您的要求创建一个辅助函数,并将数据转换为宽格式。这是一个使用 data.table
library(data.table)
setDT(data1)[, C := as.character(C)] # Make sure it's a character column
# Define the function
f <- function(x) if(is.numeric(x <- type.convert(x))) {
as.character(sum(x))
} else paste0(length(x), x)
# Rehsape
dcast(data1, ID ~ B, value.var = "C", f)
# ID Blue Green Red Yellow
# 1: 1539 12 0 22 1NCAA
# 2: 3574 0 3RA 2 0
您使用 tidyr
和 dplyr
基本上使用两个步骤来执行此操作:
spread
(tidyr
) 创建新列,名称在B
中,值在C
中
group_by
您的ID
列,然后summarize_each
其余列 (dplyr
) 使用自定义汇总函数来处理字符或数字列
这是完整的解决方案,需要更多的命令来记账。
1.传播。传播的一个陷阱是所有行都必须在某些列中有一个唯一的 id(see here)
library(dplyr)
library(tidyr)
## spread with 'convert' will convert types automatically
spread_data <- dat %>%
mutate(row= 1:nrow(dat)) %>% ## uniquely id rows
spread(B, C, convert = TRUE) %>%
select(-row)
## converting the data.frame to a tbl_df
## lets us easily see the cols are different types
tbl_df(spread_data)
##Source: local data frame [10 x 5]
##
## ID Blue Green Red Yellow
## (int) (int) (chr) (int) (chr)
## 1 1539 8 NA NA NA
## 2 1539 4 NA NA NA
## 3 1539 NA NA 9 NA
## 4 1539 NA NA 13 NA
## 5 1539 NA NA NA NCAA
## 6 3574 NA RA NA NA
## 7 3574 NA RA NA NA
## 8 3574 NA RA NA NA
## 9 3574 NA NA 1 NA
## 10 3574 NA NA 1 NA
2.分组总结。首先,我们需要编写一个函数来处理任一类型的列
summarizer <- function(x) {
if (is.numeric(x)) {
sum(x, na.rm = TRUE)
} else {
# assume x is a character
if (all(is.na(x)))
return("-")
x[is.na(x)] <- ""
x <- unique(x)
paste0(x, collapse="")
}
}
## summarize each applies summarizer to the columns that aren't being used
## for grouping (so, not ID in this case)
spread_data %>% group_by(ID) %>%
summarize_each(funs(summarizer))
##Source: local data frame [2 x 5]
##
## ID Blue Green Red Yellow
## (int) (int) (chr) (int) (chr)
## 1 1539 12 - 22 NCAA
## 2 3574 0 RA 2 -