値フィールドによる複数の行のマージ

Dec 09 2020

トリガーフィールドに応じて、これらの行を結合するにはどうすればよいですか。条件は次のとおりです。フィールドは、fidフィールドから1への後に昇順で並べ替える必要があります68。したがって、トリガー1を持つ最初の行と、値を持つ次の行で始まり、最初の値0で停止して1再開するすべての行を結合したいと思います。

編集:わかりました。しかし、どうすればこの問題を解決できますか?これらのラインを結合する方法は?トリガーは角度を指します。0の場合、2つのセグメント間の角度はx度未満であり、1の場合、角度はx度より大きくなります。したがって、最初の行がトリガーでない場合は、トリガーである最初の行と結合したいと思います。

回答

3 MrXsquared Dec 09 2020 at 19:48

これを行う方法を理解するために、Pythonで新しいgroupidフィールドを追加するソリューションを次に示します。これを使用して、行をディゾルブできます。

# Change your settings here:
layername = 'line' 
triggerfield = 'Trigger' # field must already exist
groupfieldname = 'mygroup' # will be added if does not exist
newlineindicator = 1

#####
# no changes needed below #
#####
layer = QgsProject.instance().mapLayersByName(layername)[0] # get the layer
layer.startEditing() # start editing the layer
layer.dataProvider().addAttributes([QgsField(groupfieldname,QVariant.Int)]) # add a group field
layer.commitChanges() # save new added field to prevent crash when searching for it later
layer.startEditing() # start editing the layer again
groupid = 0 # initialize groupid
fieldindex = layer.fields().indexFromName(groupfieldname) # get fieldindex of groupfield

for feat in layer.getFeatures(): # itereate over layer
    if feat[triggerfield] == newlineindicator: # if a new trigger appears, increase groupcounter
        groupid += 1
    attrs = { fieldindex : groupid } # prepare attributes
    layer.dataProvider().changeAttributeValues({ feat.id() : attrs }) # assign current groupid to current feature
layer.commitChanges() # save changes

結果:

3 Babel Dec 09 2020 at 21:08

フィールド計算機のQGIS式を使用してフィールド値を直接作成し、参加したいすべての機能をグループ化する方法があります。このフィールドの値に基づいて、関数Aggregateを使用して同じ値の機能を結合できます(下の2番目のスクリーンショットを参照)。ボットの手順は、モデルを使用して簡単に自動化できる必要があります。

データ構造とフィールド名を取得すると、式は次のようになります(式がどのように機能するかについては、以下を参照してください)。

array_last (
    array_sort (
        array_foreach (
            array_remove_all ( 
                array_agg ( 
                    if ( 
                        "trigger" = 1, 
                        "fid" , 
                        0
                    ) 
                ) ,
            0) ,
        if (
            if ( 
                "trigger" = 1, 
                "fid" , 
                0 
                ) = @element, 
                @element, 
                if (
                    "fid" > @element ,  
                    @element,0
                )
        )
        ) 
    )
)

このフィールドを関数Menu Processing / Toolbox / Aggregateと一緒に使用して、これらの機能を結合することができます。

式の背後にある考え方を説明するために、理解を深めるために、最終的に「ヘッド」を取得する結合線の「開始セグメント」と呼び、それに結合される後続のセグメントを「テール」と呼びましょう。

  1. ヘッドのfid値を取得し、「グループID」と呼びましょう。最終的な目標は、各テールセグメントをヘッドに割り当てることです(または:各テールに次に小さいヘッドグループID値を割り当てる必要があります:2と3を1、5、6から4などに割り当てる必要があります)a)トリガーが1(head)の場合、idの値を取得します。これはgroup-idです。それ以外の場合(テールの場合)は値0を設定します。b)これらの値を集計して配列を作成します。c)配列からすべての0値を削除します。したがって、グループIDの配列(=ヘッドのfid )を取得します:[1,4,7,9,12]。最後に、すべての機能を配列からこれらの値の1つに割り当てます。

  2. ここで、次の式を使用して、配列からこれらのグループIDのそれぞれを使用してレイヤーのすべての機能を繰り返します。a array_foreach)トリガー= 1(ヘッド)の機能の場合、問題はありません。これらにはすでに正しいグループIDがあります(に対応します)。それらのfid)b)その他の場合(tails、trigger = 0)、新しい値を割り当てる必要があります。したがって、配列(すべてのグループIDのリスト)からの各入力値をfidと比較し、グループIDがfidよりも小さい場合は(次に小さい値に割り当てたいため)、グループIDを保持します。それ以外の場合は0に設定します。したがって、配列からfidよりも大きい値が生成されることはありません。

  3. 配列を並べ替えて、値が正しい順序(最小から最大)になっていることを確認します。最後の位置から最後のゼロを削除します(下のスクリーンショットを参照)。並べ替え順序を設定せずに、デフォルト値を取得しますascending=true

  4. ソートされた配列から最後の値を取得します。したがって、最後の(最大の)グループIDは(ステップ2bを思い出してください)、fidより大きくない場合(trigger = 1の場合)はfid(ステップ2a)と等しくなりますANDは常に1で作成した配列の数値です。

手順1と2の中間結果については、スクリーンショットを参照してください。

これで、上記のように作成されたフィールドで集計関数を簡単に使用できます。