我无法在网上找到这个问题的解决方案,就像看起来那么简单。 这是:
#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
将所有列视为字符,就像我编写此函数一样。
答案 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
包中的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 :(得分:2)
你想使用lapply()或sapply(),而不是apply()。 data.frame是一个引擎盖下的列表,在执行任何操作之前,apply将尝试转换为矩阵。由于数据框中至少有一列是字符,因此在形成该矩阵时,每隔一列也会被强制转换为字符。