применить рассматривает числа как символы - PullRequest
1 голос
/ 11 марта 2011

Я не смог найти решение этой проблемы в Интернете, так просто, как кажется.Вот это:

#Construct test dataframe 
tf <- data.frame(1:3,4:6,c("A","A","A")) 

#Try the apply function I'm trying to use
test <- apply(tf,2,function(x) if(is.numeric(x)) mean(x) else unique(x)[1]) 

#Look at the output--all columns treated as character columns...
test

#Look at the format of the original data--the first two columns are integers. 
str(tf) 

В общих чертах, я хочу различить, какую функцию I apply по строке / столбцу, исходя из того, какой тип данных содержит эта строка / столбец.Здесь я хочу просто mean, если столбец является числовым, и первое значение unique, если столбец является символьным столбцом.Как видите, apply обрабатывает все столбцы как символы так, как я написал эту функцию.

Ответы [ 3 ]

4 голосов
/ 11 марта 2011

Просто напишите специализированную функцию и поместите ее в sapply ... не используйте apply(dtf, 2, fun). Кроме того, ваш персонаж не так характерен, как вы думаете - бегите getOption("stringsAsFactors") и убедитесь сами.

sapply(tf, class)
            X1.3             X4.6 c..A....A....A.. 
       "integer"        "integer"         "factor" 
sapply(tf, storage.mode)
            X1.3             X4.6 c..A....A....A.. 
       "integer"        "integer"        "integer"

EDIT

Или еще лучше - используйте lapply:

fn <- function(x) {
  if(is.numeric(x) & !is.factor(x)) {
    mean(x)
  } else if (is.character(x)) {
    unique(x)[1]
  } else if (is.factor(x)) {
    as.character(x)[1]
  }
}

dtf <- data.frame(a = 1:3, b = 4:6, c = rep("A", 3), stringsAsFactors = FALSE)
dtf2 <- data.frame(a = 1:3, b = 4:6, c = rep("A", 3), stringsAsFactors = TRUE)

as.data.frame(lapply(dtf, fn))
  a b c
1 2 5 A
as.data.frame(lapply(dtf2, fn))
  a b c
1 2 5 A 
3 голосов
/ 11 марта 2011

Я считаю полезными функции numcolwise и catcolwise из пакета plyr здесь для синтаксически простого решения:

Сначала давайте назовем столбцы, чтобы избежать некрасивых имен столбцов при агрегировании:

tf <- data.frame(a = 1:3,b=4:6, d = c("A","A","A"))

Тогда вы получите желаемый результат с помощью этого однострочного:

> cbind(numcolwise(mean)(tf), catcolwise( function(z) unique(z)[1] )(tf))
  a b d
1 2 5 A

Объяснение: numcolwise(f) преобразует свой аргумент (в данном случае f - это функция mean) в функцию, которая принимает фрейм данных и применяет f только к числовым столбцам фрейма данных. Точно так же catcolwise преобразует свой аргумент функции в функцию, которая работает только с категориальными столбцами.

2 голосов
/ 11 марта 2011

Вы хотите использовать lapply () или sapply (), а не применять ().Data.frame - это список изнутри, который применяет будет пытаться преобразовать в матрицу, прежде чем делать что-либо.Поскольку по крайней мере один столбец в вашем фрейме данных является символом, каждый другой столбец также приводится к символу при формировании этой матрицы.

...