2009-09-08 51 views
5

這個數據幀開始如何使R函數返回多個列並將它們附加到數據框?

myDF = structure(list(Value = c(-2, -1, 0, 1, 2)), .Names = "Value", row.names = c(NA, 5L), class = "data.frame") 

假設我要上運行的是myDF $價值

getNumberInfo <- function(x) { 
if(x %% 2 ==0) evenness = "Even" else evenness="Odd" 
if(x > 0) positivity = "Positive" else positivity = "NonPositive" 
if (positivity == "Positive") logX = log(x) else logX=NA 
c(evenness,positivity,logX) 
} 

...每一行這個函數來得到這個數據幀

structure(list(Value = c(-2, -1, 0, 1, 2), Evenness = c("Even", 
"Odd", "Even", "Odd", "Even"), Positivity = c("NonPositive", 
"NonPositive", "NonPositive", "Positive", "Positive"), Log = c(NA, 
NA, NA, "0", "0.693147180559945")), row.names = c(NA, 5L), .Names = c("Value", 
"Evenness", "Positivity", "Log"), class = "data.frame") 

回答

8

你可能想要更改getNumberInfo函數返回一個列表而不是一個向量,以便這些值可以有不同的類型。事實上,他們都被投入絃樂,這可能不是你想要的logX

getNumberInfo <- function(x) { 
    if(x %% 2 ==0) evenness = "Even" else evenness="Odd" 
    if(x > 0) positivity = "Positive" else positivity = "NonPositive" 
    if (positivity == "Positive") logX = log(x) else logX=NA 
    list(evenness,positivity,logX) 
} 

此外,還可以使用名稱稍微較好的效果,這樣你就不必贅述:

getNumberInfo <- function(x) { 
    list(evenness = if(x %% 2 ==0) "Even" else "Odd", 
     positivity = if(x > 0) "Positive" else "NonPositive", 
     logX = if(x > 0) log(x) else NA) 
} 

然後將溶液變得簡單:

> cbind(myDF, t(sapply(myDF$Value, getNumberInfo))) 
    Value evenness positivity  logX 
1 -2  Even NonPositive  NA 
2 -1  Odd NonPositive  NA 
3  0  Even NonPositive  NA 
4  1  Odd Positive   0 
5  2  Even Positive 0.6931472 

最後,如果您使用ifelse(它可以在矢量上工作)而不是if,則它變得更簡單,因爲您無需致電apply

getNumberInfo <- function(x) { 
    list(evenness = ifelse(x %% 2 ==0, "Even", "Odd"), 
     positivity = ifelse(x > 0, "Positive", "NonPositive"), 
     logX = ifelse(x > 0, log(x), NA)) 
} 

> cbind(myDF, getNumberInfo(myDF$Value)) 
    Value evenness positivity  logX 
1 -2  Even NonPositive  NA 
2 -1  Odd NonPositive  NA 
3  0  Even NonPositive  NA 
4  1  Odd Positive 0.0000000 
5  2  Even Positive 0.6931472 

最後的解決方案會發出警告,因爲它實際上是計算每個元素的日誌,而不僅僅是那些使用x>0的日誌。不知道最優雅的方式來處理。

+0

't(sapply'do)與'tapply'相反嗎?我不知道用't()'包裝什麼東西,我從來沒有見過它。 – 2016-10-09 00:11:58

3

如何:

out <- cbind(myDF, t(apply(myDF, 1, getNumberInfo))) 
colnames(out) <- c('Value', 'Evenness', 'Positivity', 'Log') 

它給你:

 
    Value Evenness Positivity    Log 
1 -2  Even NonPositive    NA 
2 -1  Odd NonPositive    NA 
3  0  Even NonPositive    NA 
4  1  Odd Positive     0 
5  2  Even Positive 0.693147180559945 

+0

是什麼'噸(apply'do而不是僅僅'tapply'我不知道是什麼東西包裝用'噸()'不,我從來沒有見過?它記錄下來。 – 2016-10-09 00:11:30

3

另一種選擇:

> library(plyr) 
> df <- mdply(myDF, getNumberInfo) 
> names(df) <- c('Value', 'Evenness', 'Positivity', 'Log') 
> df 
    Value Evenness Positivity  Log 
1 -2  Even NonPositive  NA 
2 -1  Odd NonPositive  NA 
3  0  Even NonPositive  NA 
4  1  Odd Positive 0.0000000 
5  2  Even Positive 0.6931472 
相關問題