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

3 回答 3

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 
于 2011-03-11T01:24:32.227 回答
3

我发现包中的numcolwiseandcatcolwise函数在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)将其参数(在这种情况下fmean函数)转换为一个函数,该函数接受一个数据框并且仅适用于数据框f的数字列。类似地,catcolwise将其函数参数转换为仅对分类列进行操作的函数。

于 2011-03-11T03:24:28.177 回答
2

您想使用 lapply() 或 sapply(),而不是 apply()。data.frame 是一个列表,它 apply 会在做任何事情之前尝试转换为矩阵。由于数据框中至少有一列是字符,因此在形成该矩阵时,每隔一列也会被强制转换为字符。

于 2011-03-11T01:26:21.063 回答