apply将数字视为字符

时间:2011-03-11 01:13:48

标签: r dataframe apply

我无法在网上找到这个问题的解决方案,就像看起来那么简单。 这是:

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

一般而言,我想根据行/列包含的数据类型来区分行{/ 1}上的哪个函数。

在这里,如果列是数字,我想要一个简单的apply,如果列是字符列,我想要第一个mean值。如您所见,unique将所有列视为字符,就像我编写此函数一样。

3 个答案:

答案 0 :(得分: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 

答案 1 :(得分:3)

我发现numcolwise包中的catcolwiseplyr函数在这里很有用,这是一个语法上简单的解决方案:

首先让我们为列命名,以避免在进行聚合时出现丑陋的列名:

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将其函数参数转换为仅对分类列进行操作的函数。

答案 2 :(得分:2)

你想使用lapply()或sapply(),而不是apply()。 data.frame是一个引擎盖下的列表,在执行任何操作之前,apply将尝试转换为矩阵。由于数据框中至少有一列是字符,因此在形成该矩阵时,每隔一列也会被强制转换为字符。