59

作为了解我的数据的一部分,我正在尝试获取大型数据框中每一列的最小值/最大值。我的第一次尝试是:

apply(t,2,max,na.rm=1)

它将所有内容都视为字符向量,因为前几列是字符类型。因此,某些数字列的最大值为" -99.5".

然后我尝试了这个:

sapply(t,max,na.rm=1)

但它抱怨max 对 factor 没有意义。(lapply是一样的。)让我感到困惑的是,这个apply想法max对因素来说是完全有意义的,例如它为第 1 列返回了“ZEBRA”。

顺便说一句,我看了一下Using sapply on vector of POSIXct,其中一个答案是“当你使用 sapply 时,你的对象被强制转换为数字,...... ”。这是发生在我身上的事吗?如果是这样,是否有不强制的替代应用功能?当然,这是一种常见的需求,因为数据框类型的关键特性之一是每一列都可以是不同的类型。

4

7 回答 7

44

如果它是“有序因素”,事情会有所不同。这并不是说我喜欢“有序因子”,我不喜欢,只是说某些关系是为“有序因子”定义的,而“因子”没有定义。因子被认为是普通的分类变量。您会看到因素的自然排序顺序,即您所在地区的字母词汇顺序。如果您想为每一列、...日期和因素等自动强制转换为“数字”,请尝试:

sapply(df, function(x) max(as.numeric(x)) )   # not generally a useful result

或者,如果您想先测试因素并按预期返回:

sapply( df, function(x) if("factor" %in% class(x) ) { 
            max(as.numeric(as.character(x)))
            } else { max(x) } )

@Darrens 评论确实效果更好:

 sapply(df, function(x) max(as.character(x)) )  

max字符向量确实成功。

于 2011-09-05T02:24:03.907 回答
21

max使用的原因applyapply首先将您的数据框强制为矩阵,并且矩阵只能保存一种数据类型。所以你最终得到一个字符矩阵。sapply只是 的包装器lapply,因此两者产生相同的错误也就不足为奇了。

创建数据框时的默认行为是将分类列存储为因子。除非您指定它是一个有序因子,否则类似max和的操作min将是未定义的,因为 R 假设您已经创建了一个无序因子。

您可以通过指定来更改此行为options(stringsAsFactors = FALSE),这将更改整个会话的默认值,或者您可以传入stringsAsFactors = FALSE构造data.frame()调用本身。请注意,这仅意味着默认情况minmax将假定“按字母顺序”排序。

或者您可以手动为每个因素指定排序,尽管我怀疑这是您想要做的。

无论如何,sapply通常会产生一个原子向量,这将需要在许多情况下将所有内容转换为字符。一种解决方法如下:

#Some test data
d <- data.frame(v1 = runif(10), v2 = letters[1:10], 
                v3 = rnorm(10), v4 = LETTERS[1:10],stringsAsFactors = TRUE)

d[4,] <- NA

#Similar function to DWin's answer          
fun <- function(x){
    if(is.numeric(x)){max(x,na.rm = 1)}
    else{max(as.character(x),na.rm=1)}
}   

#Use colwise from plyr package
colwise(fun)(d)
         v1 v2       v3 v4
1 0.8478983  j 1.999435  J
于 2011-09-05T02:30:26.633 回答
7

如果您想了解您的数据,请summary (df)提供数值列的最小值、第 1 分位数、中位数和平均值、第 3 分位数和最大值以及因子列的最高级别的频率。

于 2011-09-05T07:25:59.243 回答
3

最好的方法是避免使用基*apply函数,它将整个数据帧强制为一个数组,可能会丢失信息。

如果你想对as.numeric每一列应用一个函数,一个简单的方法是使用mutate_allfrom dplyr

t %>% mutate_all(as.numeric)

或者使用colwisefrom plyr,它将“将对向量进行操作的函数转换为在 data.frame 上按列操作的函数”。

t %>% (colwise(as.numeric))

在读取字符向量数据表并将列强制转换为正确数据类型的特殊情况下,请使用type.convertor type_convertfrom readr.


不太有趣的答案:我们可以使用 for 循环对每一列应用:

for (i in 1:nrow(t)) { t[, i] <- parse_guess(t[, i]) }

我不知道在保留数据帧结构的同时使用 *apply 进行分配的好方法。

于 2019-08-01T06:16:15.290 回答
2

以@ltamar 的回答为基础:
使用摘要并将输出转换为有用的东西!

library(tidyr)
library(dplyr)

df %>% 
  summary %>% 
  data.frame %>%
  select(-Var1) %>%
  separate(data=.,col=Freq,into = c('metric','value'),sep = ':') %>%
  rename(column_name=Var2) %>%
  mutate(value=as.numeric(value),
         metric = trimws(metric,'both') 
  ) %>%  
  filter(!is.na(value)) -> metrics

它不漂亮,当然也不快,但它完成了工作!

于 2018-06-13T12:59:53.460 回答
0

根据可行性,使用retype()从 hablar 强制因子转换为字符或数字类型的解决方案。我将dplyr用于将 max 应用于每一列。

代码

library(dplyr)
library(hablar)

# Retype() simplifies each columns type, e.g. always removes factors
d <- d %>% retype()

# Check max for each column
d %>% summarise_all(max)

结果

不是新的列类型。

     v1 v2       v3 v4   
  <dbl> <chr> <dbl> <chr>
1 0.974 j      1.09 J   

数据

# Sample data borrowed from @joran
d <- data.frame(v1 = runif(10), v2 = letters[1:10], 
                v3 = rnorm(10), v4 = LETTERS[1:10],stringsAsFactors = TRUE)
于 2019-08-01T06:15:59.093 回答
0
df <- head(mtcars)
df$string <- c("a","b", "c", "d","e", "f"); df

my.min <- unlist(lapply(df, min))
my.max <- unlist(lapply(df, max))
于 2021-01-26T09:50:14.060 回答