2017-09-08 8 views
4

J'utilise la structure data.tree pour résumer diverses informations à travers les dossiers de fichiers. Dans chaque dossier, j'ai un certain nombre de fichiers (Value), et ce que je dois faire pour chaque dossier est de résumer combien de fichiers le dossier + tous les sous-dossiers contiennent.R: Comment résumez-vous les données pour les feuilles et les nœuds dans Data.Tree?

données Exemple:

library(data.tree) 
data <- data.frame(pathString = c("MainFolder", 
            "MainFolder/Folder1", 
            "MainFolder/Folder2", 
            "MainFolder/Folder3", 
            "MainFolder/Folder1/Subfolder1", 
            "MainFolder/Folder1/Subfolder2"), 
        Value = c(1,1,5,2,4,10)) 
tree <- as.Node(data, Value) 
print(tree, "Value") 
       levelName Value 
1 MainFolder    1 
2 ¦--Folder1   1 
3 ¦ ¦--Subfolder1  4 
4 ¦ °--Subfolder2 10 
5 ¦--Folder2   5 
6 °--Folder3   2 

Ma solution actuelle et très lent au problème:

# Function to sum up file counts pr folder + subfolders 
total_count <- function(node) { 
    results <- sum(as.data.frame(print(node, "Value"))$Value) 
    return(results) 
} 

# Summing up file counts pr folder + subfolders 
tree$Do(function(node) node$Value_by_folder <- total_count(node)) 


# Results 
print(tree, "Value", "Value_by_folder") 
      levelName Value Value_by_folder 
1 MainFolder    1    23 
2 ¦--Folder1   1    15 
3 ¦ ¦--Subfolder1  4    4 
4 ¦ °--Subfolder2 10    10 
5 ¦--Folder2   5    5 
6 °--Folder3   2    2 

Avez-vous une suggestion de la façon de le faire plus efficacement? J'ai essayé de construire une méthode récursive, et aussi d'utiliser les fonctions "isLeaf" et "enfants" sur les nœuds, mais je n'ai pas réussi à le faire fonctionner.

Répondre

1

Ceci est un moyen efficace de le faire. Il utilise l'API data.tree et stocke la valeur dans l'arborescence:

MyAggregate <- function(node) { 
    if (node$isLeaf) return (node$Value) 
    sum(Get(node$children, "Value_by_folder")) + node$Value 
} 

tree$Do(function(node) node$Value_by_folder <- MyAggregate(node), traversal = "post-order") 
+0

Merci, je vais tester les deux réponses aujourd'hui. Celui-ci a l'air le plus propre, mais y a-t-il une raison pour que ce ne soit pas return (sum (get $ node, "Value_by_folder")) + node $ Value)? –

+0

Non, c'est identique. Les fonctions R renvoient toujours la dernière valeur. –

+0

@EsbenEickhardt Pas sûr de votre définition de nettoyeur, mais cela devrait être plus lent, je pense. Pouvez-vous nous indiquer les résultats de l'analyse comparative de votre plus grand ensemble de données? –

1

Vous pouvez faire:

get_value_by_folder <- function(tree) { 

    res <- rep(NA_real_, tree$totalCount) 

    i <- 0 
    myApply <- function(node) { 
    i <<- i + 1 
    force(k <- i) 
    res[k] <<- node$Value + `if`(node$isLeaf, 0, sum(sapply(node$children, myApply))) 
    } 

    myApply(tree) 
    res 
} 

Le force est important parce que l'évaluation paresseuse de R bousille l'ordre que vous voulez remplir res.

Et vous obtenez:

> get_value_by_folder(tree) 
[1] 23 15 4 10 5 2 

Edit: si vous voulez le remplir dans l'arbre directement.

get_value_by_folder2 <- function(tree) { 

    myApply <- function(node) { 
    node$Value_by_folder <- node$Value + `if`(node$isLeaf, 0, sum(sapply(node$children, myApply))) 
    } 

    myApply(tree) 
    tree 
} 

> print(get_value_by_folder2(tree), "Value", "Value_by_folder") 
      levelName Value Value_by_folder 
1 MainFolder    1    23 
2 ¦--Folder1   1    15 
3 ¦ ¦--Subfolder1  4    4 
4 ¦ °--Subfolder2 10    10 
5 ¦--Folder2   5    5 
6 °--Folder3   2    2 

Notez que la classe est un environnement pour que soit modifié le tree d'origine.

> print(tree, "Value", "Value_by_folder") 
      levelName Value Value_by_folder 
1 MainFolder    1    23 
2 ¦--Folder1   1    15 
3 ¦ ¦--Subfolder1  4    4 
4 ¦ °--Subfolder2 10    10 
5 ¦--Folder2   5    5 
6 °--Folder3   2    2 
+0

Cela enregistre-t-il la valeur dans l'arborescence? –

+0

@EsbenEickhardt Nop. Je pensais que vous le vouliez comme un vecteur pour une utilisation plus facile. Je vais mettre à jour ma réponse. –