2017-09-08 5 views
4

私はdata.tree構造体を使用して、ファイルフォルダ間のさまざまな情報を要約しています。各フォルダにはいくつかのファイル(値)があり、各フォルダに対して何を行う必要があるのは、フォルダ+すべてのサブフォルダに含まれるファイルの数を要約することです。R:Data.Treeのリーフとノードの両方のデータをどのように要約しますか?

例データ:問題へ

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 

私の現在、非常にSLOWソリューション:あなたはより効率的にこれを行う方法の提案を

# 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 

を持っていますか?私は再帰的な方法を構築しようとしており、ノード上で関数 "isLeaf"と "children"を使用することも試みてきましたが、それを動作させることはできませんでした。あなたが行うことができます

答えて

1

これは効率的な方法です。これは、data.tree APIを使用し、値をツリーに格納します。

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

ありがとう、私は今日2つの答えをテストします。これは最もきれいに見えますが、返されない理由があります(合計(Get $ node children、 "Value_by_folder"))+ node $ Value)? –

+0

いいえ、それは同じです。 R関数は常に最後の値を返します。 –

+0

@EsbenEickhardtクリーナーの定義についてはわかりませんが、これはもっと遅くなるはずです。より大きなデータセットのベンチマーク結果を教えてください。 –

1

:Rの遅延評価は、あなたがresを埋めるためにしたいために台無しにするので

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 
} 

forceが重要です。

そして、あなたが得る:

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

編集:をあなたが直接ツリーでそれを埋めるためにしたい場合。

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 

treeが変更されるように、クラス環境であることに留意されたいです。

> 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

この値をツリーに保存しますか? –

+0

@EsbenEickhardt Nop。私はあなたが簡単に使うためのベクターとしてそれを望んだと思った。私は私の答えを更新します。 –

関連する問題