0

私の目的は、R の 2 つの列間の共有値に基づいて、単一のデータ フレーム内の「接続された」行を識別することです。

この例では、10 個の一意のセグメント (つまり、データのクラスタ) があり、それぞれの一意のセグメントに対応する整数によって識別されます。各行は、互いに特定の距離のしきい値内にあると既に判断されている 2 つのセグメントを表します。列「segA」と「segB」の間に大きな違いはありません。これらは、接続されているセグメントのペアを追跡するためにのみ使用されます。列「距離」は、セグメントのペア間の距離を表しますが、データ フレームには「接続されている」と見なされるセグメントのペアのみが含まれているため、この時点では実際には必要ありません。

行間の接続セグメントを示す、「segA」または「segB」に少なくとも 1 つの共有値を持つすべての行を識別する方法を見つけようとしています。

私の最初の試みは、ループと論理ステートメントに対して複雑でした (R プログラミングは初めてです)。そのため、簡潔な解決策があれば大歓迎です!

例:

 df = data.frame(
  segA = c(1, 1, 2, 4, 6, 7, 9),
  segB = c(2, 3, 4, 5, 8, 8, 10),
  dist = c(0.5321, 0.3212, 0.4351, 0.1421, 0.5125, 0.1692, 0.3218)
 )

df
  segA segB   dist
1    1    2 0.5321
2    1    3 0.3212
3    2    4 0.4351
4    4    5 0.1421
5    6    8 0.5125
6    7    8 0.1692
7    9   10 0.3218

行 1 と 2 は、両方ともセグメント "1" を含むため、接続されています。

行 3 と 1 は、どちらもセグメント "2" を含むため、接続されています。

行 2 と行 3 は共有セグメントの存在によって直接接続されていませんが、行 1 を介した相互接続によって全体的に接続されています。

望ましい最終出力は次のようになります。

(1) = 1, 2, 3, 4, 5  
(2) = 6, 7, 8  
(3) = 9, 10  

ここで、(1)、(2)、および (3) は、別個の全体セグメントと、直接/相互に接続されたそれらのコンポーネントを表します。

4

1 に答える 1

0
## helper function for merging vector elements of a list
merge.elems <- function(x,i,j) {
    c(
        x[seq_len(i-1L)], ## before i
        list(unique(c(x[[i]],x[[j]]))), ## combined i,j
        x[seq_len(j-i-1L)+i], ## between i,j
        x[seq_len(length(x)-j)+j] ## after j
    );
}; ## end merge.elems()

## initialize row groups and value groups
rgs <- as.list(seq_len(nrow(df)));
vgs <- do.call(Map,c(c,unname(df[1:2])));

## if there are 2 or more groups, exhaustively merge overlapping value group pairs
if (length(rgs)>1L) {
    i <- 1L;
    j <- 2L;
    repeat {
        if (any(vgs[[i]]%in%vgs[[j]])) {
            rgs <- merge.elems(rgs,i,j);
            vgs <- merge.elems(vgs,i,j);
            j <- i+1L;
            if (j>length(rgs)) break;
        } else {
            j <- j+1L;
            if (j>length(rgs)) {
                i <- i+1L;
                if (i==length(rgs)) break;
                j <- i+1L;
            }; ## end if
        }; ## end if
    }; ## end repeat
}; ## end if

## results
rgs;
## [[1]]
## [1] 1 2 3 4
##
## [[2]]
## [1] 5 6
##
## [[3]]
## [1] 7
##
vgs;
## [[1]]
## [1] 1 2 3 4 5
##
## [[2]]
## [1] 6 8 7
##
## [[3]]
## [1]  9 10
##
于 2016-05-12T02:59:31.970 に答える