Wie kann eine R -Funktion mehrere Spalten zurückgeben und an einen Datenrahmen anhängen?

StackOverflow https://stackoverflow.com/questions/1395156

  •  21-09-2019
  •  | 
  •  

Frage

Beginnend mit diesem Datenrahmen

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

Angenommen, ich möchte diese Funktion in jeder Reihe von MyDF $ Value ausführen

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)
} 

... um diesen Datenrahmen zu erhalten

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")
War es hilfreich?

Lösung

Vielleicht möchten Sie Ihre ändern getNumberInfo Funktionieren Sie eine Liste anstelle eines Vektors, damit die Werte unterschiedliche Typen haben können. So wie es ist, werden sie alle in Saiten gegossen, was wahrscheinlich nicht das ist, was Sie wollen 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)
}

Darüber hinaus können Sie die Namen zu einem etwas besseren Effekt verwenden, damit Sie sie nicht wiederholen müssen:

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)
}

Dann wird die Lösung einfach:

> 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

Schließlich, wenn Sie verwenden ifelse (was an Vektoren funktionieren kann) anstelle von if, Es wird noch einfacher, weil Sie nicht anrufen müssen 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

Diese letzte Lösung gibt eine Warnung aus, da sie tatsächlich das Protokoll jedes Elements berechnet, nicht nur diejenigen mit x>0. Ich bin mir nicht sicher, ob der eleganteste Weg, damit umzugehen.

Andere Tipps

Wie wäre es mit:

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

Was dir gibt:

  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

Eine andere Alternative:

> 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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top