2012-03-08 40 views
3

我需要使用R *應用功能,使教程初學者(不使用在第一次重塑或plyr包)訪問數據幀的列名和*應用功能

我嘗試lapply(因爲我讀apply是不好的數據幀)一個簡單的功能這個數據幀,我想用命名的列來訪問數據:

fDist <- function(x1,x2,y1,y2) { 
    return (0.1*((x1 - x2)^2 + (y1-y2)^2)^0.5) 
} 

data <- read.table(textConnection("X1 Y1 X2 Y2 
1 3.5 2.1 4.1 2.9 
2 3.1 1.2 0.8 4.3 
")) 

data$dist <- lapply(data,function(df) {fDist(df$X1 , df$X2 , df$Y1 , df$Y2)}) 

我有這樣的錯誤$ operator is invalid for atomic vectors,很可能是因爲數據幀由laply修改? ..有沒有最好的方式來做到這一點與$命名列?

我用@DWin回答解決了我的第一個問題。但我有另一個問題,誤解,與混合數據幀(數字+字符):

在我的新用例,我使用兩個函數來計算距離,因爲我的目標是比較所有其他點之間的距離點。

data2 <- read.table(textConnection("X1 Y1 X2 Y2 
    1 3.5 2.1 4.1 2.9 
    2 3.1 1.2 0.8 4.3 
    ")) 

data2$char <- c("a","b") 

fDist <- function(x1,y1,x2,y2) { 
return (0.1*((x1 - x2)^2 + (y1-y2)^2)^0.5) 
} 

fDist2 <- function(fixedX,fixedY,vec) { 
fDist(fixedX,fixedY,vec[['X2']],vec[['Y2']]) 
} 

# works with data (dataframe without character), but not with data2 (dataframe with character) 
#ok 
data$f_dist <- apply(data, 1, function(df) {fDist2(data[1,]$X1,data[1,]$Y1,df)}) 
#not ok 
data2$f_dist <- apply(data2, 1, function(df) {fDist2(data2[1,]$X1,data2[1,]$Y1,df)}) 
+2

如果你正在循環一個數據幀的列,這是'lapply'做的,內部函數一次只能看到一列。 – 2012-03-08 21:20:14

回答

8

在這種情況下apply是你所需要的。所有的數據列都是相同的類型,您不擔心丟失屬性,這是應用程序導致問題的地方。您將需要以不同的方式寫你的功能,所以它只是需要長度爲4的一個載體:

fDist <- function(vec) { 
    return (0.1*((vec[1] - vec[2])^2 + (vec[3]-vec[4])^2)^0.5) 
         } 
data$f_dist <- apply(data, 1, fDist) 
data 
    X1 Y1 X2 Y2 f_dist 
1 3.5 2.1 4.1 2.9 0.1843909 
2 3.1 1.2 0.8 4.3 0.3982462 

如果你想在「數據」使用的列名的時候,他們需要正確拼寫:

fDist <- function(vec) { 
    return (0.1*((vec['X1'] - vec['X2'])^2 + (vec['Y1']-vec['Y2'])^2)^0.5) 
         } 
data$f_dist <- apply(data, 1, fDist) 
data 
#--------  
X1 Y1 X2 Y2 f_dist 
1 3.5 2.1 4.1 2.9 0.1000000 
2 3.1 1.2 0.8 4.3 0.3860052 

您更新(以及非常不同)的問題很容易解決。當您使用apply時,它會強制使用最低的共同模式分母,在這種情況下爲「字符」。你有兩個選擇:要麼1)添加as.numeric您的所有參數的函數中,或2)只發送所需的列,我將說明:

data2$f_dist <- apply(data2[ , c("X2", "Y2") ], 1, function(coords) 
             {fDist2(data2[1,]$X1,data2[1,]$Y1, coords)}) 

我真的不喜歡你是如何傳遞參數給這個函數。在形式表中使用「[」和「$」只是看起來不對。「你應該知道「df」不是一個數據框,而是一個矢量。因爲它不是數據框(或列表),所以你應該改變裏面的函數,使它使用「[」而不是「[[」。既然你只需要兩個座標,那麼只需要傳遞你將要使用的兩個(數字)座標。

+0

我有一些問題,我的數據幀轉換爲fDist,不明白爲什麼: 'fDist2 < - function(X1,X2,columnVector){fDist(X1,X2,as.numeric(columnVector [[「X」 ]])as.numeric(columnVector [[「Y」]]))}和 'apply(data99_07,1,function(df){fDist2(data99_07 [data99_07 $ CODCOM == 75101,] $ X, data99_07 [data99_07 $ CODCOM == 75101,] $ Y,df)}) 我需要進行轉換,因爲匿名函數返回一個字符向量:/ – reyman64 2012-03-09 16:24:42

+0

如果一列vec是class「factor」,那麼approved方法是使用'as.numeric(as.character(vec)'將其轉換爲數字,不能只使用'as.numeric(vec)'並獲得可解釋的結果 – 2012-03-09 17:43:14

+0

在anonymous函數之前,columnVector是數字的,它是一個角色矢量,所以我需要將其轉換爲數字進行計算,那麼可能應用或匿名函數使向量的隱式轉換成爲可能嗎? – reyman64 2012-03-09 21:00:07

5

作爲邊注,通常,其最好避免使用data作爲自基礎R的功能的變量名:

dat <- read.table(textConnection("X1 Y1 X2 Y2 
1 3.5 2.1 4.1 2.9 
2 3.1 1.2 0.8 4.3 
")) 

lapply饋送data.frame的單個列到功能。

lapply(dat, function(df) print(df)) 

取而代之,你想要apply。但是它將一行作爲一個向量進行輸入,它不使用$運算符。相反,您可以直接編制索引:

apply(dat, 1, function(vec) {fDist(vec[1] , vec[3] , vec[2] , vec[4])}) 

或者重寫函數以將位置參數作爲附加參數。

fDist <- function(vec, pos1, pos2, pos3, pos4) { 
    return (0.1*((vec[pos1] - vec[pos2])^2 + (vec[pos3]-vec[pos4])^2)^0.5) 
} 

apply(dat, 1, fDist, pos1=1, pos2=3, pos3 = 2, pos4=4) 

然而,最好的解決辦法是完全矢量化的功能:

fDist <- function(df) { 
    return (0.1*((df$X1 - df$X2)^2 + (df$Y1-df$Y2)^2)^0.5) 
}