如何在R中得到完整数据框的所有列的频率表?

8

我希望从一个数据框中创建一个频率表并将其保存在Excel中。使用table()函数,我只能创建特定列的频率。但我想为所有的列一起创建频率表,对于每一列,变量的级别或类型也可能不同。就像一个数据框的摘要,但没有均值或其他措施,只有频率。

我尝试着像这样:

 for(i in 1:230){
 rm(tb)
 tb<-data.frame(table(mydata[i]))
 tb2<-cbind(tb2,tb)
 }

但它显示以下错误:

Error in data.frame(..., check.names = FALSE) : arguments imply differing number of rows: 15, 12

我曾尝试使用data.frame()替换cbind(),但错误没有改变。


1
lapply(mydata,table)是怎么样的呢? - scoa
错误意味着tb2包含15行,而tb只包含12行。 - Verena Haunschmid
我刚刚尝试了lapply(mydata,table),并尝试使用write.csv将其保存在csv文件中,但是它产生了一个错误Error in data.frame(s_id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, : arguments imply differing number of rows: 24066, 27558, 17779, 18466, 3, 15, 5, 12, 13, 10, 4, 9, 7, 2, 21, 20, 51, 14, 23, 24, 31, 6, 26, 8, 55, 576, 1027, 2459, 363, 1973, 765。当我尝试对结果使用data.frame()时也出现了相同的错误。 - Sankar Narayan Misra
正如你所说,变量的级别可能不同。你如何期望创建一个包含所有变量频率的数据框架?你可以尝试像最小值、最大值、平均值和频率这样的操作,因为无论如何,所有列都会产生3个值。 - AntoniosK
3个回答

8
你会收到一个错误提示,因为你试图合并具有不同维度的数据框。据我所知,你的问题有两个方面: (1) 无论类型如何,你想获得每列的频率分布; (2) 你想将所有结果保存在单个Excel表中。
对于第一个问题,你可以使用mapply()函数。
set.seed(1)

dat <- data.frame(
  x = sample(LETTERS[1:5], 15, replace = TRUE),
  y = rbinom(5, 15, prob = 0.4)
)

mylist <- mapply(table, dat); mylist

# $x
# 
# A B C D E 
# 2 5 1 4 3 
# 
# $y
# 
# 5  6  7 11 
# 3  3  6  3 

您也可以使用purrr :: map()
library(purrr)
dat %>% map(table)

这个问题有几种解决方案,可以在这个链接中找到:在R中将列表导出为CSV或TXT文件。特别是,LyzandeR的答案将使您能够实现您想要的功能。如果您希望将输出保存在单独的文件中,可以执行以下操作:
mapply(write.csv, mylist, file=paste0(names(mylist), '.csv'))

6
也许使用rbind方法会更好,因为它可以处理具有不同水平的变量:
dt = data.frame(x = c("A","A","B","C"),
                y = c(1,1,2,1))

dt

#   x y
# 1 A 1
# 2 A 1
# 3 B 2
# 4 C 1

dt_res = data.frame()

for (i in 1:ncol(dt)){

dt_temp = data.frame(t(table(dt[,i])))
dt_temp$Var1 = names(dt)[i]

dt_res = rbind(dt_res, dt_temp)

}

names(dt_res) = c("Variable","Levels","Freq")

dt_res

#   Variable Levels Freq
# 1        x      A    2
# 2        x      B    1
# 3        x      C    1
# 4        y      1    3
# 5        y      2    1

另一种(可能更快)使用apply的进程:

dt = data.frame(x = c("A","A","B","C"),
                y = c(1,1,2,1))

dt

ff = function(x){

  y = data.frame(t(table(x)))
  y$Var1 = NULL
  names(y) = c("Levels","Freq")
  return(y)
}

dd = do.call(rbind, apply(dt, 2, ff)) 

dd

#     Levels Freq
# x.1      A    2
# x.2      B    1
# x.3      C    1
# y.1      1    3
# y.2      2    1


# extract variable names from row names
dd$Variable = sapply(row.names(dd), function(x) unlist(strsplit(x,"[.]"))[1])

dd

#     Levels Freq Variable
# x.1      A    2        x
# x.2      B    1        x
# x.3      C    1        x
# y.1      1    3        y
# y.2      2    1        y

2

编辑(2021-03-29):tidyverse 原则

这里有一些更新的代码,使用了 tidyverse ,具体包括 dplyrtibblepurrr 函数。代码更易读且更易执行。提供了示例数据集。

tibble(
    a = rep(c(1:3), 2),
    b = factor(rep(c("Jan", "Feb", "Mar"), 2)),
    c = factor(rep(LETTERS[1:3], 2))
    ) -> 
    dat

dat #print df

# A tibble: 6 x 3
    a    b    c    
  <int> <fct> <fct>
1     1 Jan   A    
2     2 Feb   B    
3     3 Mar   C    
4     1 Jan   A    
5     2 Feb   B    
6     3 Mar   C

获取跨列的计数和比例。
library(purrr)
library(dplyr)
library(tibble)
#library(tidyverse) #to load assortment of pkgs

#output tables - I like to use parentheses & specifying my funs
purrr::map(
    dat, function(.x) {
        count(tibble(x = .x), x) %>% 
            mutate(pct = (n / sum(n) * 100)) 
        })

#here is the same code but more concise (tidy eval)
purrr::map(dat, ~ count(tibble(x = .x), x) %>% 
               mutate(pct = (n / sum(n) * 100)))

$a
# A tibble: 6 x 3
      x     n   pct
  <int> <int> <dbl>
1     1     1  16.7
2     2     1  16.7
3     3     1  16.7
4     4     1  16.7
5     5     1  16.7
6     6     1  16.7

$b
# A tibble: 3 x 3
  x         n   pct
  <fct> <int> <dbl>
1 Feb       2  33.3
2 Jan       2  33.3
3 Mar       2  33.3

$c
# A tibble: 2 x 3
  x         n   pct
  <fct> <int> <dbl>
1 A         3    50
2 B         3    50

旧代码...

table()函数返回一个"表"对象,在我看来,使用R很难操作。我倾向于编写自己的函数来解决这个问题。让我们首先创建一个含有一些分类变量/特征(宽格式数据)的数据框。

我们可以使用lapply()与基础R中的table()函数相结合,创建每个特征的频率计数列表。

freqList = lapply(select_if(dat, is.factor), 
              function(x) {
                  df = data.frame(table(x))
                  names(df) = c("x", "y")
                  
                  return(df) 
                    }
                )

该方法允许每个列表对象容易地进行索引并在必要时进一步操作,这对于包含许多特征的数据框架非常方便。使用print(freqList)查看所有频率表。

如果需要多列的比例表(例如,占总观察量百分比),则可以尝试我的帖子此处 - DataSci-IOPsy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接