Примените функцию к каждому столбцу во фрейме данных, наблюдая за существующим типом данных каждого столбца. - PullRequest
48 голосов
/ 05 сентября 2011

Я пытаюсь получить мин / макс для каждого столбца в большом кадре данных, как часть знакомства с моими данными . Моя первая попытка была:

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

Он обрабатывает все как символьный вектор, потому что первые несколько столбцов являются типами символов. Таким образом, максимум некоторых числовых столбцов выглядит как " -99.5".

Я тогда попробовал это:

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

но он жалуется на макс, не значимый для факторов . (lapply - это то же самое.) Меня смущает то, что apply мысль max была совершенно значимой для факторов, например, он возвратил "ЗЕБРА" для столбца 1.

Кстати, я взглянул на Использование sapply для вектора POSIXct и один из ответов гласит: " Когда вы используете sapply, ваши объекты приводятся в числовое значение, ... ». Это то, что происходит со мной? Если да, есть ли альтернативная функция apply, которая не приводит к принудительному выполнению? Конечно, это общая потребность, так как одна из ключевых особенностей типа фрейма данных состоит в том, что каждый столбец может быть другого типа.

Ответы [ 4 ]

35 голосов
/ 05 сентября 2011

Если бы это был «упорядоченный фактор», все было бы иначе. Это не значит, что мне нравятся «упорядоченные факторы», я не хочу только сказать, что некоторые отношения определены для «упорядоченных факторов», которые не определены для «факторов». Факторы рассматриваются как обычные категориальные переменные. Вы видите естественный порядок сортировки факторов, который является алфавитным лексическим порядком для вашей локали. Если вы хотите получить автоматическое приведение к «числовому» для каждого столбца, ... дат, факторов и всего, попробуйте:

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) } )

@ Комментарий Даррена работает лучше:

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

max успешно с символьными векторами.

17 голосов
/ 05 сентября 2011

Причина, по которой max работает с apply, заключается в том, что apply сначала приводит ваш кадр данных к матрице, и матрица может содержать только один тип данных.Таким образом, вы получите матрицу символов.sapply - это просто оболочка для lapply, поэтому неудивительно, что оба выдают одну и ту же ошибку.

Поведение по умолчанию при создании фрейма данных для категориальных столбцов, которые должны храниться как факторы .Если вы не укажете, что это упорядоченный коэффициент , такие операции, как max и min, будут неопределенными, поскольку R предполагает, что вы создали неупорядоченный фактор.

Вы можете изменить это поведение, указав options(stringsAsFactors = FALSE), который изменит значение по умолчанию для всего сеанса, или вы можете передать stringsAsFactors = FALSE в самом вызове конструкции data.frame().Обратите внимание, что это просто означает, что min и max примут «алфавитный» порядок по умолчанию.

Или вы можете вручную указать порядок для каждого фактора, хотя я сомневаюсь, что это то, что вы хотите сделать.

Независимо от этого, 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
7 голосов
/ 05 сентября 2011

Если вы хотите узнать свои данные, summary (df) предоставляет минимальный, 1-й квантиль, медиану и среднее, 3-й квантиль и максимум числовых столбцов и частоту верхних уровней столбцов факторов.

2 голосов
/ 13 июня 2018

основываясь на ответе @ 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

Это не красиво и, конечно, не быстро, но оно выполняет свою работу!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...