在 R 中使用 dplyr 和 reshape2 为列范围内的每个因子水平生成表
Generating tables for each factor level over a range of columns, in R with dplyr and reshape2
对于数据框中的一系列列(变量),我需要为每个变量的每个级别生成 tables。我创建了一个函数,用于查找范围 (Q1a) 中的第一列,然后为之后的每一列运行一个 for 循环。该循环查找每一列中的级别数,然后第二个 for 循环应该生成 table 并将其保存为具有唯一文件名的 .csv。
示例数据框:
df <- data.frame(Organization = c("A", "B", "C", "D"), Gender = c("Male", "Female", "Male", "Female"), Q1a = c(1, 2, 3, 4), Q1b = c(1, 2, 1, 2))
df Returns:
Organization Gender Q1a Q1b
1 A Male 1 1
2 B Female 2 2
3 C Male 3 1
4 D Female 4 2
这是我写的函数:
library(dplyr)
library(reshape2)
f = function(df) {
a <- which(colnames(df) == "Q1a")
for(i in colnames(df[, a:length(df)])) {
levelsList <- as.list(levels(i))
for(j in levelsList) {
temp <- subset(df, i == j, select = c(Organization, Gender, i))
temp <- group_by(temp, Organization, Gender)
table <- summarize(temp, count = n())
table <- dcast(table, Organization ~ Gender)
table <- mutate(table, Total = Female + Male)
write.csv(table, paste0(i, "_", j, ".csv"))
}
}
}
较大数据集的预期输出如下所示:
Organization Female Male Total
1 A 366 259 625
2 B 30 35 65
3 C 83 61 144
4 D 55 58 113
我可以用几行代码正确地生成一个像上面那样的 table。问题是该函数不生成任何文件。我在正确的轨道上吗?有没有更简单的方法使用应用来做到这一点?
我修改的几个问题。查看循环中 i
的值。它是来自 df
的列名的字符串值。当传递给 levels()
时,您将永远得到 NULL
。如果您真的想使用 levels()
,您需要将这些列转换为因子,或者替换为 unique()
。
请参阅 ?subset
下的警告部分以了解如何使用此函数,我已将代码更改为使用 [
对数据框进行子集化。
此外,我假设您打算将 table
输出到 CSV,而不是您的示例中不存在的 org.sum
。
library(dplyr)
library(reshape2)
df <- data.frame(Organization = c("A", "A", "B", "C", "D"), Gender = c("Male", "Female", "Female", "Male", "Female"), Q1a = as.factor(c(1, 1, 2, 3, 4)), Q1b = as.factor(c(1, 1, 2, 1, 2)))
f = function(df) {
a <- which(colnames(df) == "Q1a")
for(i in colnames(df[, a:length(df)])) {
levelsList <- levels(df[,i])
for(j in levelsList) {
temp <- df[df[,i] == j, c('Organization', 'Gender', i)]
temp <- group_by(temp, Organization, Gender)
table <- summarize(temp, count = n())
table <- dcast(table, Organization ~ Gender, value.var='count')
if (dim(table)[2] > 2) {table$Total <- rowSums(table[,c('Male', 'Female')])}
else {table$Total <- table[,2]}
write.csv(table, paste0(i, "_", j, ".csv"), row.names = F)
}
}
}
f(df)
对于数据框中的一系列列(变量),我需要为每个变量的每个级别生成 tables。我创建了一个函数,用于查找范围 (Q1a) 中的第一列,然后为之后的每一列运行一个 for 循环。该循环查找每一列中的级别数,然后第二个 for 循环应该生成 table 并将其保存为具有唯一文件名的 .csv。
示例数据框:
df <- data.frame(Organization = c("A", "B", "C", "D"), Gender = c("Male", "Female", "Male", "Female"), Q1a = c(1, 2, 3, 4), Q1b = c(1, 2, 1, 2))
df Returns:
Organization Gender Q1a Q1b
1 A Male 1 1
2 B Female 2 2
3 C Male 3 1
4 D Female 4 2
这是我写的函数:
library(dplyr)
library(reshape2)
f = function(df) {
a <- which(colnames(df) == "Q1a")
for(i in colnames(df[, a:length(df)])) {
levelsList <- as.list(levels(i))
for(j in levelsList) {
temp <- subset(df, i == j, select = c(Organization, Gender, i))
temp <- group_by(temp, Organization, Gender)
table <- summarize(temp, count = n())
table <- dcast(table, Organization ~ Gender)
table <- mutate(table, Total = Female + Male)
write.csv(table, paste0(i, "_", j, ".csv"))
}
}
}
较大数据集的预期输出如下所示:
Organization Female Male Total
1 A 366 259 625
2 B 30 35 65
3 C 83 61 144
4 D 55 58 113
我可以用几行代码正确地生成一个像上面那样的 table。问题是该函数不生成任何文件。我在正确的轨道上吗?有没有更简单的方法使用应用来做到这一点?
我修改的几个问题。查看循环中 i
的值。它是来自 df
的列名的字符串值。当传递给 levels()
时,您将永远得到 NULL
。如果您真的想使用 levels()
,您需要将这些列转换为因子,或者替换为 unique()
。
请参阅 ?subset
下的警告部分以了解如何使用此函数,我已将代码更改为使用 [
对数据框进行子集化。
此外,我假设您打算将 table
输出到 CSV,而不是您的示例中不存在的 org.sum
。
library(dplyr)
library(reshape2)
df <- data.frame(Organization = c("A", "A", "B", "C", "D"), Gender = c("Male", "Female", "Female", "Male", "Female"), Q1a = as.factor(c(1, 1, 2, 3, 4)), Q1b = as.factor(c(1, 1, 2, 1, 2)))
f = function(df) {
a <- which(colnames(df) == "Q1a")
for(i in colnames(df[, a:length(df)])) {
levelsList <- levels(df[,i])
for(j in levelsList) {
temp <- df[df[,i] == j, c('Organization', 'Gender', i)]
temp <- group_by(temp, Organization, Gender)
table <- summarize(temp, count = n())
table <- dcast(table, Organization ~ Gender, value.var='count')
if (dim(table)[2] > 2) {table$Total <- rowSums(table[,c('Male', 'Female')])}
else {table$Total <- table[,2]}
write.csv(table, paste0(i, "_", j, ".csv"), row.names = F)
}
}
}
f(df)