2011-03-11 32 views
1

我无法在线找到此问题的解决方案,就像看起来那么简单。 这里,它是:将数字视为字符

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

总体而言,我想我apply通过行/列基于什么类型的行/列包含数据的什么功能来区分。

在这里,如果列是数字,我想要一个简单的mean,如果列是字符列,则需要第一个unique值。正如你所看到的,apply将所有列视为我写这个函数的方式。

回答

4

只写一个专门的功能,并把它放在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" 

编辑

甚至更​​好 - 使用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 
+0

这正是答案 - 谢谢!欢呼所有贡献:) – Aaron

+0

我忘了添加'stringsToFactors = FALSE',因为列'c'的类默认为'factor'。你可能想要设置'options(stringsAsFactors = FALSE)',否则,你会得到一个'factor'。被告知。 – aL3xa

2

你想用lapply()或sapply(),不适用()。 data.frame是引擎盖下的一个列表,应用程序会在做任何事情之前尝试转换为矩阵。由于数据框中至少有一列是字符,所以其他列也被强制转换为形成该矩阵的字符。

+0

没错,矩阵只能保存一种类型的数据:'is.atomic(matrix())'产生'TRUE' – aL3xa

3

我找到了plyr包有用的numcolwisecatcolwise功能在这里,对于语法简单的解决方案:

首先让我们命名的栏目,做聚合时,为了避免难看的列名:

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)将其参数(在这种情况下,fmean函数)转换为采用数据帧并将f仅应用于数据帧的数字列的函数。同样,catcolwise将其函数参数转换为仅在分类列上运行的函数。