6

土壌タイプ

ルックアップのために、この三角グラフのデータを表現しようとしています。3つの値すべてを関数にフィードして、これらの値がどの領域カテゴリに分類されるかを取得できるようにしたいと思います。私が見ているアプローチは、デカルト座標を使用して各領域をポリゴンに変換することです。次に、指定された値をポイントに変換し、そのポイントがどのポリゴン内にあるかを確認します。私はそれがうまくいくとかなり確信していますが、それは単純なルックアップにはやり過ぎのように見えますか?

単純なルックアップで十分になるように、このグラフのデータを配列またはオブジェクトで表す方法があるかどうかを尋ねています。

4

2 に答える 2

4

上記をデカルト座標系に変換することはできますが、実際にこれを行うために必要な重要な側面が欠けていると思います。

上の図では、ポリゴンを2次元構造として見ていますが、3次元の点があります。結局のところ、上の2次元平面上に三角形が表示されることは不可能ではありませんが、デカルト空間への変換は正確には単純ではありません。

むしろ、これは決定木のグラフィック表現に非常によく似ています。この表現を作成するために、粘土、シルト、砂の量を読み取ったようです。

基本的に、3つの値のタプルがあり、それらの値に応じて分類を取得する必要があります。

上記の場合、分類「シルト」の決定木を次のようにモデル化できます。

// These are approximate based on above.  Each branch of the
// tree is evaluated on one value out of all the values.
if (silt >= .8)
{
    // True case.  Check sand content.
    if (sand >= .20)
    {
        // Something else, other branches.
    }
    else
    {
        // False case, can possibly be silt.
        if (clay >= .125)
        {
            // Something else, other branches.
        }
        else
        {
            // Leaf, this is a classification.
            // Can return more strongly typed classification if you want.
            return "silt";
        }            
    }

}
else
{
    // Something else, other branches.
}

if/elseステートメントは、決定木のブランチを表します。各ブランチで、ブランチのその時点で最も多くの情報が得られる変数の値を評価する必要があります(ほとんどの場合、その分割からいくつの分類を行うことができますか?)。その変数を決定する際のエントロピー(または不確実性)。

ツリーは自動的に生成することも、手動でコーディングすることもできます。後者は可能ですが、それを開発するための自動化/コードベースの方法を強くお勧めします。Accord.NET(AForge.NETが必要です。どちらも優れています)を確認することを強くお勧めします。開始するには、 Accord.NETを使用して決定木を作成する方法を示すこのブログ投稿を参照してください。

どちらの方法でも、最終的には3つの値(粘土、シルト、砂)を受け取り、それぞれの値に応じてツリーをトラバースして分類を返す関数を取得します。

(最初のコードサンプルに見られるように)各分類にマップされる1対1の基準(ブランチ)のセットが必ずしも必要ではないことに注意してください。上記の例のポリゴン上の頂点の数に応じて、これらの状況を処理するために追加のブランチが必要になります。

元のサンプルデータがある場合は、デシジョンツリービルダーでサンプルデータを実行するだけで、上記のようなデシジョンツリーが作成されます。

元のサンプルデータがない場合は、上からの頂点を使用してそれらを分類して作成できます。例えば:

silt    sand    clay    classification
----    ----    ----    --------------
   0      50     100    clay (top point)
 100       0      50    silt (right bottom point)
  50     100       0    sand (left bottom point)
  15      45      40    sandy clay OR clay cloam OR clay (depending on splits)
...

最後の行(および後続の行)に関しては、決定木はそれらの値に基づいて境界を設定し、連続しているため、通常、その値以上のすべての値に基づいて決定を行います。

于 2012-09-20T20:14:47.753 に答える
2

これを行う方法は、あなたが提案したように、「ポリゴンのポイントアプローチ」を使用することです。つまり、これを視覚的に行う場合、それはまさに頭の中で行っていることです。受け入れられた答えの問題は、この場合(および単純な場合)、決定木を構築できる可能性がある一方で、より多くのカテゴリーがある状況では、このプロセスが非常に複雑なIMHOになることです。おそらくカテゴリは重複しています。おそらくカテゴリは単一のポイントにすぎません。ここで提案するプロセスでは、これらのアーティファクトは結果に影響を与えません。

ggternパッケージで提供されるデータセットに基づいて、USDA土壌分類図の作成、以下に添付する結果については、すでにここで説明しました。

ここに画像の説明を入力してください

しかし、それほど明確ではないかもしれませんが、ggternパッケージには、これを必要以上に面倒にする機能がいくつかあるということです。具体的には、ggternパッケージ(バックエンドで日常的に使用される)には、参照カテゴリに対して各ポイントのポリゴン真理値表のポイントを評価するために必要な変換を行うための内部関数がいくつかあります。

このようなアプローチは、 plyrパッケージのddply関数、およびspパッケージのpoint.in.polygon関数を使用するとかなり簡単です。

まず、必要なパッケージをロードし、ggternからUSDAデータをロードします。また、いくつかのサンプルデータを作成し、頂点にある点と分類領域の中心にある点についてこのプロセスをテストしてみましょう。

library(ggtern)
library(sp)
library(plyr)

#The Main Data to lookup against
data(USDA)

#The sample Data (Try a point at a vertice, and a point in the middle...)
testData = rbind(data.frame(Clay=.4,Sand=.2,Silt=.4), #Vertice point
                 data.frame(Clay=1,Sand=1,Silt=1)/3)  #Simple middle point

次に、内部関数、を使用して、transform_tern_to_cart(...)両方のデータセットをデカルト座標に変換することをお勧めします。

#Do the transformation to cartesian
USDA[,c("x","y")]     = transform_tern_to_cart(USDA$Clay,USDA$Sand,USDA$Silt)
testData[,c("x","y")] = transform_tern_to_cart(testData$Clay,testData$Sand,testData$Silt)

ddply(...)との組み合わせをapply(...)使用することにより、関数を使用して、参照セットの各カテゴリに対して、テストセットの各ポイントをテストできpoint.in.polygon(...)ます。

#Create a function to do the lookup
lookup <- function(data=testData,lookupdata=USDA,groupedby="Label"){  
  if(!groupedby %in% colnames(lookupdata))
    stop("Groupedby value is not a column of the lookupdata")

  #For each row in the data
  outer = apply(data[,c("x","y")],1,function(row){

    #for each groupedby in the lookupdata
    inner = ddply(lookupdata,groupedby,function(df){
      if(point.in.polygon(row[1],row[2],df$x,df$y) > 0) #Is in polygon?
        return(df) #Return a valid dataframe
      else
        return(NULL) #Return nothing
    })

    #Extract the groupedby data from the table
    inner = unique(inner[,which(colnames(inner) == groupedby)])

    #Join together in csv string and return to 'outer'
    return(paste(as.character(inner),collapse=","))
  })

  #Combine with the original data and return
  return(cbind(data,Lookups=outer))
}

これは、次の方法で呼び出すことができます。

#Execute
lookup()

予想どおり、最初のポイントは4つのカテゴリを満たし、2番目のポイントは1つだけを満たしていることに気付くでしょう。

于 2014-04-05T00:51:20.420 に答える