我知道必須有一個簡單的答案,這但不知何故,我似乎無法找到它的...實施輪廓查詢或有效邊界
我有2個數字列的數據幀。 我想從中刪除具有該屬性的行,在數據框中至少存在另一行,並且列值都大於此行中的行值。
所以,如果我有
Col1 Col2
1 2 3
2 4 7
3 5 6
我想刪除的第一行,因爲第二個滿足的財產,只保留行2和3
非常感謝!
我知道必須有一個簡單的答案,這但不知何故,我似乎無法找到它的...實施輪廓查詢或有效邊界
我有2個數字列的數據幀。 我想從中刪除具有該屬性的行,在數據框中至少存在另一行,並且列值都大於此行中的行值。
所以,如果我有
Col1 Col2
1 2 3
2 4 7
3 5 6
我想刪除的第一行,因爲第二個滿足的財產,只保留行2和3
非常感謝!
這個問題被數據庫管理員(他們可能有其他算法)稱爲「天際線查詢」,經濟學家稱之爲「有效前沿」。 繪製數據可以清楚地表明我們在尋找什麼。
n <- 40
d <- data.frame(
x = rnorm(n),
y = rnorm(n)
)
# We want the "extreme" points in the following plot
par(mar=c(1,1,1,1))
plot(d, axes=FALSE, xlab="", ylab="")
for(i in 1:n) {
polygon(c(-10,d$x[i],d$x[i],-10), c(-10,-10,d$y[i],d$y[i]),
col=rgb(.9,.9,.9,.2))
}
的算法如下:沿第一點 排序協調,保持各觀測,除非它是比上保留一個更糟糕。
d <- d[ order(d$x, decreasing=TRUE), ]
result <- d[1,]
for(i in seq_len(nrow(d))[-1]) {
if(d$y[i] > result$y[nrow(result)]) {
result <- rbind(result, d[i,]) # inefficient
}
}
points(result, cex=3, pch=15)
是的,這正是我想要做的,但我認爲這樣做「C」的方式是不合適的,謝謝一堆! – user1184143 2012-02-02 04:03:43
好的情節和見解。 – 2012-02-02 14:59:42
+1,謝謝你的好評。我特別感謝你與天際線查詢建立連接,然後包括一個情節,以說明爲什麼它有這個名字!我已經在下面添加了一個答案,靈感來自你的,它用更多的R-ish矢量化構造替換了for()'循環。 – 2012-02-02 17:07:26
d <- matrix(c(2, 3, 4, 7, 5, 6), nrow=3, byrow=TRUE)
d2 <- sapply(d[, 1], function(x) x < d[, 1]) &
sapply(d[, 2], function(x) x < d[, 2])
d2 <- apply(d2, 2, any)
result <- d[!d2, ]
嗯,我並不完全理解這一點,但我的感覺是,它不會分別查看每一列。舉例來說,如果您的行>(d,c)(c(2,3,3,7,5,6,4,8),nrow = 4,byrow = TRUE)row(3,7)也應該被移除,因爲4,8)在兩列中都較大。感謝您的回覆。 – user1184143 2012-02-02 04:14:39
對,我誤解了你的要求。我讀它的意思是「如果B行中的每個數字大於A行中的每個數字,排除行A」。因爲4和8每個都不大於3和7(即4不大於7),所以不符合標準,並且不排除該行。現在我明白你對B行的值是否大於A行相應列的值感興趣。我已經編輯了答案來糾正它(我認爲)。 – jbaums 2012-02-02 04:49:51
(現在應該排除那些行存在的每一列中有較大值的行,我相信Vincent的解決方案將排除另一行存在的行在每列中具有較大*或相等*值的行,儘管這可能確實是您打算寫在你的問題..?) – jbaums 2012-02-02 06:26:55
在一個行:
d <- matrix(c(2, 3, 4, 7, 5, 6), nrow=3, byrow=TRUE)
d[!apply(d,1,max)<max(apply(d,1,min)),]
[,1] [,2]
[1,] 4 7
[2,] 5 6
編輯:在jbaums的迴應你的精密光亮,這裏是如何單獨檢查兩個列。
d <- matrix(c(2, 3, 3, 7, 5, 6, 4, 8), nrow=4, byrow=TRUE)
d[apply(d,1,min)>min(apply(d,1,max)) ,]
[,1] [,2]
[1,] 5 6
[2,] 4 8
但是,我需要獨立對待每個列,例如,如果我有d < - 矩陣(c(1,8,7,2),nrow = 2,byrow = TRUE ),因爲第一行在第二列中具有最高值而第二行在第一列中具有最高值,因此在兩個**列中都沒有其他行具有較高值,所以應該保留兩行。 – user1184143 2012-02-04 01:33:34
下面是一個sqldf解決方案,其中DF
是數據的數據幀:
library(sqldf)
sqldf("select * from DF a
where not exists (
select * from DF b
where b.Col1 >= a.Col1 and b.Col2 > a.Col2
or b.Col1 > a.Col1 and b.Col2 >= a.Col2
)"
)
編輯(2015年3月2日):對於更有效的解決方案,請參閱帕特里克Roocks' rPref,用於「數據庫首選項和天際線計算」的包(也在以下答案中鏈接)。爲了表明它找到與我的代碼相同的解決方案,我在這裏附加了一個使用它的例子。
Riffing關文森特Zoonekynd的啓發性反應的,這裏是一個算法的完全矢量化,並有可能更有效:
set.seed(100)
d <- data.frame(x = rnorm(100), y = rnorm(100))
D <- d[order(d$x, d$y, decreasing=TRUE), ]
res <- D[which(!duplicated(cummax(D$y))), ]
# x y
# 64 2.5819589 0.7946803
# 20 2.3102968 1.6151907
# 95 -0.5302965 1.8952759
# 80 -2.0744048 2.1686003
# And then, if you would prefer the rows to be in
# their original order, just do:
d[sort(as.numeric(rownames(res))), ]
# x y
# 20 2.3102968 1.6151907
# 64 2.5819589 0.7946803
# 80 -2.0744048 2.1686003
# 95 -0.5302965 1.8952759
或者使用RPREF包:
library(rPref)
psel(d, high(x) | high(y))
# x y
# 20 2.3102968 1.6151907
# 64 2.5819589 0.7946803
# 80 -2.0744048 2.1686003
# 95 -0.5302965 1.8952759
非常優雅!謝謝。 – user1184143 2012-02-04 01:43:58
這個問題很舊,但同時有一個新的解決方案。我希望在這裏做一些自我推銷是可以的:我開發了一個包rPref,它由於C++算法而進行了有效的Skyline計算。安裝RPREF包從查詢有問題可以通過(假設df
是數據集的名稱)來完成:
library(rPref)
psel(df, high(Col1) | high(Col2))
這消除了只有那些元組,其中一些其他的元組是在兩個維度上更好。
如果需要另一個元組在一個維度上嚴格更好(並且在另一個維度上更好或相等),請改爲使用high(Col1) * high(Col2)
。
哈!剛剛點擊了你的個人資料,看到了'rPref'的鏈接,然後直奔這裏,記下現在有一個更好的解決方案。會在我的回答中添加一個註釋,指向這裏的人,因爲否則你的答案几乎在雜草中消失了! – 2015-03-02 17:23:25
這個包是否處理有兩個以上變量的有效邊界?假設我們想要包含n變量 – 2015-03-06 00:24:56
是的,它的確如此。變量/維度的數量沒有主要限制,即高(x1)|高(x2)| ... |高(xn)'也是可能的,但計算成本(以及運行時間)將隨着維數的增加而增加。 – 2015-03-11 08:15:12
我無法設置編輯,因爲它只有空格,但是您的表格可以使用代碼格式:在每行之前放置一個額外的4個空格,並且它將以與您使用的格式相同的格式出現它更具可讀性。 – Jeff 2012-02-02 02:41:49
謝謝傑夫,我試圖找出如何做到這一點,但我失敗了。 – user1184143 2012-02-02 04:01:49