按因子列聚合混合数据
Aggregating mixed data by factor column
在过去的一周里,我一直在尝试汇总我的数据集,该数据集包含不同月份的不同体重测量值以及 R 中的大量背景变量。
我已经阅读了许多关于这个主题的不同问题(即 R aggregate data by defining grouping, ), but they all seem to either only work with one type of data or are only interested in one column. Specifically, question 处理几乎完全相同的问题,但建议的答案只解决了分类数据的问题,它不包括数字数据也。我的数据由因素(分类和序数)和数字数据组成。
可重现的例子是:
IDnumber <- c("1", "1", "1", "2", "2", "3", "3", "3")
Gender <- c("Male", "Male", "Male", "Female", "Female", "Female", "Female", "Female")
Weight <- c(80, 82, 82, 70, 66, 54, 50, 52)
LikesSoda <- c("Yes", "No", "No", "Yes", "Yes", "Yes", "Yes", NA)
df = data.frame(IDnumber, Gender, Weight, LikesSoda)
我的输出数据框将采用每个数字列的平均值,以及每个因子列的最常见因子。在示例中,这将如下所示:
IDnumber <- c("1", "2", "3")
Gender <- c("Male", "Female", "Female")
Weight <- c(81.5, 78, 52)
LikesSoda <- c("No", "Yes", "Yes")
output = data.frame(IDnumber, Gender, Weight, LikesSoda)
到目前为止,我已经尝试将数据框拆分为一个因子数据框和一个数字数据框,并使用两个具有不同函数的聚合(意味着数字,但我一直无法找到一个工作函数分类数据)。另一种选择是使用 dplyr df &>& group_by(IDnumber) %>% summarise( transformation for each variable )
代码,但这需要我指定如何手动处理每一列。由于我有超过 2500 列,这似乎不是一个可行的解决方案。
您可以编写自己的函数,然后使用 lapply
。首先,编写一个函数来查找因子变量中出现频率最高的水平
getmode <- function(v) {
levels(v)[which.max(table(v))]
}
然后根据传递给它的变量类型写一个函数到return均值或众数
my_summary <- function(x, id, ...){
if (is.numeric(x)) {
return(tapply(x, id, mean))
}
if (is.factor(x)) {
return(tapply(x, id, getmode))
}
}
最后,使用lapply
计算汇总
data.frame(lapply(df, my_summary, id = df$IDnumber))
IDnumber Gender Weight LikesSoda
1 1 Male 81.33333 No
2 2 Female 68.00000 Yes
3 3 Female 52.00000 Yes
如果一个因素中可能有两个或更多水平具有相同的最大频率,那么 which.max
将只是 return 第一个水平。我从你的评论中了解到你只想知道其中有多少,所以一种选择可能是稍微修改 getmode
函数,这样当出现平局时它会在级别上添加一个星号:
getmode <- function(v) {
tab <- table(v)
if (sum(tab %in% max(tab)) > 1) return(paste(levels(v)[which.max(tab)], '*'))
levels(v)[which.max(tab)]
}
(更改您的示例数据,以便 IDnumber ==“2”的一名女性和一名男性)
data.frame(lapply(df, my_summary, id = df$IDnumber))
IDnumber Gender Weight LikesSoda
1 1 Male 81.33333 No
2 2 Female * 68.00000 Yes
3 3 Female 52.00000 Yes
恐怕这有点乱 'solution',但如果您只是想了解该问题的普遍程度,也许它足以满足您的需求。
在过去的一周里,我一直在尝试汇总我的数据集,该数据集包含不同月份的不同体重测量值以及 R 中的大量背景变量。
我已经阅读了许多关于这个主题的不同问题(即 R aggregate data by defining grouping,
可重现的例子是:
IDnumber <- c("1", "1", "1", "2", "2", "3", "3", "3")
Gender <- c("Male", "Male", "Male", "Female", "Female", "Female", "Female", "Female")
Weight <- c(80, 82, 82, 70, 66, 54, 50, 52)
LikesSoda <- c("Yes", "No", "No", "Yes", "Yes", "Yes", "Yes", NA)
df = data.frame(IDnumber, Gender, Weight, LikesSoda)
我的输出数据框将采用每个数字列的平均值,以及每个因子列的最常见因子。在示例中,这将如下所示:
IDnumber <- c("1", "2", "3")
Gender <- c("Male", "Female", "Female")
Weight <- c(81.5, 78, 52)
LikesSoda <- c("No", "Yes", "Yes")
output = data.frame(IDnumber, Gender, Weight, LikesSoda)
到目前为止,我已经尝试将数据框拆分为一个因子数据框和一个数字数据框,并使用两个具有不同函数的聚合(意味着数字,但我一直无法找到一个工作函数分类数据)。另一种选择是使用 dplyr df &>& group_by(IDnumber) %>% summarise( transformation for each variable )
代码,但这需要我指定如何手动处理每一列。由于我有超过 2500 列,这似乎不是一个可行的解决方案。
您可以编写自己的函数,然后使用 lapply
。首先,编写一个函数来查找因子变量中出现频率最高的水平
getmode <- function(v) {
levels(v)[which.max(table(v))]
}
然后根据传递给它的变量类型写一个函数到return均值或众数
my_summary <- function(x, id, ...){
if (is.numeric(x)) {
return(tapply(x, id, mean))
}
if (is.factor(x)) {
return(tapply(x, id, getmode))
}
}
最后,使用lapply
计算汇总
data.frame(lapply(df, my_summary, id = df$IDnumber))
IDnumber Gender Weight LikesSoda
1 1 Male 81.33333 No
2 2 Female 68.00000 Yes
3 3 Female 52.00000 Yes
如果一个因素中可能有两个或更多水平具有相同的最大频率,那么 which.max
将只是 return 第一个水平。我从你的评论中了解到你只想知道其中有多少,所以一种选择可能是稍微修改 getmode
函数,这样当出现平局时它会在级别上添加一个星号:
getmode <- function(v) {
tab <- table(v)
if (sum(tab %in% max(tab)) > 1) return(paste(levels(v)[which.max(tab)], '*'))
levels(v)[which.max(tab)]
}
(更改您的示例数据,以便 IDnumber ==“2”的一名女性和一名男性)
data.frame(lapply(df, my_summary, id = df$IDnumber))
IDnumber Gender Weight LikesSoda
1 1 Male 81.33333 No
2 2 Female * 68.00000 Yes
3 3 Female 52.00000 Yes
恐怕这有点乱 'solution',但如果您只是想了解该问题的普遍程度,也许它足以满足您的需求。