Подтвердить что ты не робот

Применить функцию к каждому столбцу в кадре данных, наблюдая за каждым столбцом существующий тип данных

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

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

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

Затем я попробовал это:

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

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

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

4b9b3361

Ответ 1

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

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 выполняется с символьными векторами.

Ответ 2

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

Поведение по умолчанию при создании фрейма данных предназначено для хранения категориальных столбцов в качестве факторов. Если вы не укажете, что это упорядоченный коэффициент, операции типа max и min будут undefined, так как 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 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

Ответ 3

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

Ответ 4

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

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

Ответ 5

Решение с использованием retype() от хаблара до принудительных факторов к символьному или числовому типу в зависимости от осуществимости. Я бы использовал dplyr для применения максимума к каждому столбцу.

Код

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   

Data

данных
# Sample data borrowed from @joran
d <- data.frame(v1 = runif(10), v2 = letters[1:10], 
                v3 = rnorm(10), v4 = LETTERS[1:10],stringsAsFactors = TRUE)

Ответ 6

Абсолютно лучший способ сделать это - избегать применения базовых * функций, которые приводят весь массив данных к массиву, и использовать colwise из plyr. (Я удивлен, что никто не упомянул об этом)

Пример использования parse_guess в качестве функции, которая работает со всеми видами векторных типов данных:

colwise(parse_guess)(t)

Менее интересный ответ: мы можем применить к каждому столбцу цикл for:

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

Я не знаю, как выполнять назначение с помощью * apply, сохраняя структуру фрейма данных.