2011-03-11 56 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將其函數參數轉換爲僅在分類列上運行的函數。