这是dplyr 包的解决方案。
理论上,实际代码可能仅限于一行
library(dplyr)
# ...
for(nom in names(df)) write.table(df %>% count(!!sym(nom)) %>% mutate(sot = n/sum(n)), 'stat.csv', sep = ';', row.names = FALSE, append = TRUE)
产生输出文件stat.csv
"age";"n";"sot"
21;1;0.2
32;1;0.2
33;1;0.2
45;1;0.2
46;1;0.2
"gender";"n";"sot"
"female";3;0.6
"male";2;0.4
"income";"n";"sot"
"high";1;0.2
"low";3;0.6
"medium";1;0.2
"education";"n";"sot"
"high";3;0.6
"medium";2;0.4
但为了清晰起见,我选择使用 cmets 分解工作流程:
library(dplyr)
# ...
# Code to generate `df`
# ...
# Create list to accumulate the summaries
results <- list()
# For each variable (by name) in `df`...
for(nom in names(df)) {
# ...append to the list the results of summarizing by that variable.
results <- c(
results,
# Wrap summary in a `list` to append properly:
list(
df %>%
# Interpret the variable name as the variable itself, within the context
# of `df`; and count the occurrences of each of the values that variable
# takes on within `df`.
count(!!sym(nom)) %>%
# Sum up the counts to reconstruct the total amount; then divide the
# count `n` by that total, to obtain `sot`.
mutate(sot = n/sum(n))
) %>%
# Name that summary after the variable.
setNames(nm = nom)
)
}
# View results
results
鉴于您的示例df 在此处复制
structure(
list(
age = c(45 , 21 , 32 , 33 , 46 ),
gender = c("female", "female", "male" , "male" , "female"),
income = c("low" , "low" , "medium", "high" , "low" ),
education = c("high" , "high" , "high" , "medium", "medium")
),
class = "data.frame",
row.names = c(NA, -5L)
)
此工作流程应产生以下 list 或 results:
$age
age n sot
1 21 1 0.2
2 32 1 0.2
3 33 1 0.2
4 45 1 0.2
5 46 1 0.2
$gender
gender n sot
1 female 3 0.6
2 male 2 0.4
$income
income n sot
1 high 1 0.2
2 low 3 0.6
3 medium 1 0.2
$education
education n sot
1 high 3 0.6
2 medium 2 0.4
我的解决方案涵盖了df 中的每个变量,但您可以通过修改for-loop 来排除age 等变量。
要将所有这些写成文件stat.csv,并在您的代码中以; 分隔,只需完成:
for(summr in results) {
write.table(
x = summr,
file = 'stat.csv',
sep = ';',
row.names = FALSE,
append = TRUE
)
}