2015-06-18 16 views
5

"Singletons'u" ikili matristen çıkarmaya çalışıyorum. Burada, singletonlar, satırda ve göründükleri sütundaki tek "1" değeri olan öğelere başvurur. 1. [3,4], çünkü (mümkünse sütun 4 hepsi ve)Satırları/sütunları bir ikili matristen yalnızca bir öğe ile kaldırma

> matrix(c(0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1), nrow=6) 
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] 
[1,] 0 1 0 0 0 0 0 
[2,] 1 0 1 0 0 0 0 
[3,] 0 0 0 1 0 0 0 
[4,] 1 1 0 0 0 0 0 
[5,] 0 0 0 0 1 1 1 
[6,] 0 0 0 0 1 0 1 

... ı satır 3 kaldırmak için eder: Örneğin, aşağıdaki matris verilen Bu satır/sütun kombinasyonunda sadece 1. [1,2] iyi, çünkü sütunda diğer 1'ler var [, 2]; benzer şekilde [2,3] iyidir, çünkü diğer 1'ler satırda [2]. Herhangi bir yardım takdir edilecektir - teşekkürler!

cevap

3

Önce hangi satırların ve sütunların tekil olduğunu bulmak ve sonra bir dizin paylaşan tek sütun satır ve sütun çiftleri olup olmadığını kontrol etmek. İşte kısa bir kod biraz bu görevi başarmak için: Bu biraz daha verimli hale getirmek gerekebilir birçok sinlgeton ros veya sütunlar ile

foo <- matrix(c(0,1,0,...)) 
singRows <- which(rowSums(foo) == 1) 
singCols <- which(colSums(foo) == 1) 
singCombinations <- expand.grid(singRows, singCols) 
singPairs <- singCombinations[apply(singCombinations, 1, 
    function(x) which(foo[x[1],] == 1) == x[2]),] 
noSingFoo <- foo[-unique(singPairs[,1]), -unique(singPairs[,2])] 

, ama iş yok.

GÜNCELLEME: Yapılabilecek daha verimli bir sürüm. Bu şekilde, yalnızca tüm satırları (veya istenirse sütunları) ve tüm kombinasyonları değil. Bu nedenle, birçok tekil satır/sütun içeren matrisler için çok daha verimlidir.

## starting with foo and singRows as before 
singPairRows <- singRows[sapply(singRows, function(singRow) 
    sum(foo[,foo[singRow,] == 1]) == 1)] 
singPairs <- sapply(singPairRows, function(singRow) 
    c(singRow, which(foo[singRow,] == 1))) 
noSingFoo <- foo[-singPairs[1,], -singPairs[2,]] 

GÜNCELLEME 2: I rbenchmark paketi kullanılarak (madeni = nonsparse ve Chris en = seyrek @) iki yöntem karşılaştırdık. Bir dizi matris boyutu (10'dan 1000'e kadar satır/sütun; sadece kare matrisler) ve sparsity seviyelerini (satır/sütun başına 0,1 ila 5 adet sıfır olmayan girişten) kullandım. Göreceli performans seviyesi aşağıdaki ısı haritasında gösterilmektedir. Eşit performans (çalışma zamanlarının log2 oranı) beyaz ile işaretlenir, seyrek yöntemle daha hızlıdır ve seyrek olmayan yöntemle daha hızlıdır. Performans hesaplamasındaki seyrek bir matrise dönüşümü dahil etmediğimi, dolayısıyla seyrek yönteme biraz zaman ekleyeceğimi unutmayın. Sadece bu sınırın nerede olduğunu görmek için biraz çaba göstermeye değer olduğunu düşündüm. Relative Performance

+0

çok serin, görselleştirme için teşekkür ederiz. Tamdan seyrekliğe dönüşüm önemsizdir, tüm matris üzerinde döngü yaparak ve sıfır olmayan her bir değerin koordinatlarını çekerek clümen olarak yaptım (bunu yapacak paketlerin de olduğuna inanıyorum). Bu, büyük matrisler için (yine, daha fazla 1MM^n için [n boyutlar için işe yaradığı için]), seyrek, hem bellek hem de hesaplamalar için daha uygun bir çözümdür ve matrisin zaten bunun içinde olacağını varsayabilirim. biçim. – Chris

+0

Seyrekliğe dönüştürme o kadar da zor değil (cevabım için yorumuma bakın). Ve aslında seyrek metot çok büyük matrisler için daha verimlidir, sadece standart matris formatını koruyan bir yöntem sağladım. – cr1msonB1ade

2

cr1msonB1ade'nin yolu harika bir cevaptır. seyrek gösterimde sizin matris kodlayın

:

DT <- structure(list(i = c(1, 2, 2, 3, 4, 4, 5, 5, 5, 6, 6), j = c(2, 
                  1, 3, 4, 1, 2, 5, 6, 7, 5, 7), val = c(1, 1, 1, 1, 1, 1, 1, 1, 
                            1, 1, 1)), .Names = c("i", "j", "val"), row.names = c(NA, -11L 
                            ), class = "data.frame") 

verir (0'lar örtülü olan)

> DT 
    i j val 
1 1 2 1 
2 2 1 1 
3 2 3 1 
4 3 4 1 
5 4 1 1 
6 4 2 1 
7 5 5 1 
8 5 6 1 
9 5 7 1 
10 6 5 1 
11 6 7 1 

Sonra biz daha yoğun hesaplama gerektiren matrisleri (milyon x milyon) için, bu yöntemi kullanabilirsiniz

DT <- data.table(DT) 

DT[, rowcount := .N, by = i] 
DT[, colcount := .N, by = j] 

verilmesi: kullanarak filtre edebilirsiniz

>DT[!(rowcount*colcount == 1)] 
    i j val rowcount colcount 
1: 1 2 1  1  2 
2: 2 1 1  2  2 
3: 2 3 1  2  1 
4: 4 1 1  2  2 
5: 4 2 1  2  2 
6: 5 5 1  3  2 
7: 5 6 1  3  1 
8: 5 7 1  3  2 
9: 6 5 1  2  2 
10: 6 7 1  2  2 

((3,4) satır şimdi eksik Not) 691.363.210

+0

Kaba sürümün daha verimli hale gelip gelmediğini görmek için iki yöntemimizi karşılaştırmaya çalışıyorum. İlk iki sütunu 'nonZeroIndices <- ile hesaplayabilirsiniz (foo! = 0, arr.ind = TRUE). – cr1msonB1ade

İlgili konular