假設我有一個資料框
mydata <- data.frame(x = 1:25,
y = 26:50)
和另一個具有一組最小值和最大值的資料框
df.remove <- data.frame(min = c(3,10,22,17),
max = c(6,13,24,20))
我希望創建一個輸出,其中洗掉 mydata 列 x 中的值的行,這些行位于 df.remove 中的 min 和 max 的每一行之間。因此給了我一個輸出資料框
x y
1 26
2 27
7 32
8 33
9 34
14 39
15 40
16 41
21 46
25 50
我想我可以使用 between() 函式來洗掉介于某個范圍之間的值,并且因為我會查看 df.remove 中每一行的最小值和最大值,所以我嘗試使用代碼運行一個回圈
result <- data.frame()
for(i in 1:nrow(df.filter)) {
result <- mydata[!between(mydata$x,df.filter$min[i],df.filter$max[i]),]
}
出于顯而易見的原因,這會回傳僅洗掉最后一組最小值和最大值的輸出。我想得到我正在尋找的輸出我可能不得不對前一次迭代的輸出而不是原始資料幀 mydata 運行連續迭代,但是我找不到方法來做到這一點。
uj5u.com熱心網友回復:
在您的代碼中,結果資料框只能保留您的最后一次更新,因為您對原始mydata資料框進行了操作,并且每次都將這個單一更新分配給結果資料框。
相反,您應該對更新的資料框進行操作。你可以試試下面的代碼。
result <- mydata
for(i in 1:nrow(df.remove)) {
result <- result[!between(result$x,df.remove$min[i],df.remove$max[i]),]
}
將原始mydata資料框分配給結果資料框后,您可以以迭代的方式對其進行更新。
uj5u.com熱心網友回復:
您正在尋找的東西被稱為非平等反加入。這可以通過 data.table 包輕松完成。考慮
library(data.table)
mydata <- data.frame(x = 1:25, y = 26:50)
df.remove <- data.frame(min = c(3,10,22,17), max = c(6,13,24,20))
setDT(mydata)[!df.remove, on = .(x >= min, x <= max)] # drop rows where min <= x <= max
輸出
x y
1: 1 26
2: 2 27
3: 7 32
4: 8 33
5: 9 34
6: 14 39
7: 15 40
8: 16 41
9: 21 46
10: 25 50
uj5u.com熱心網友回復:
基本 R 方法 -
res <- subset(mydata, !x %in% unlist(Map(`:`, df.remove$min, df.remove$max)))
res
# x y
#1 1 26
#2 2 27
#7 7 32
#8 8 33
#9 9 34
#14 14 39
#15 15 40
#16 16 41
#21 21 46
#25 25 50
使用我們在和值Map之間創建序列,它們在單個向量中,如果具有相同的值,則洗掉行。minmaxunlistx
fuzzyjoin使用包的另一種選擇-
fuzzyjoin::fuzzy_anti_join(mydata, df.remove,
c('x' = 'min', 'x' = 'max'),
match_fun = c(`>=`, `<=`))
uj5u.com熱心網友回復:
由于您之間使用 dplyr 功能,我們可以使用 dplyr 過濾功能。對于要在 df.remove 的每一行之間應用的 mydata 的每一行,以查看 x 列的值是否介于兩者之間。這可以通過 mapply 來完成(因為有兩個值要輸入到函式中)。這將創建一個 T/F 矩陣。然后遍歷每一行,看看是否有任何值作為 T 回傳。使用 apply 跨行執行此操作。對任何回傳 T 表示目標值之間的值的行的負過濾器:
library(dplyr)
mydata %>%
filter(
!mapply(function(left, right) between(mydata$x, left, right), left = df.remove$min, right = df.remove$max) %>%
apply(., 1, any)
)
回報:
x y
1 1 26
2 2 27
3 7 32
4 8 33
5 9 34
6 14 39
7 15 40
8 16 41
9 21 46
10 25 50
uj5u.com熱心網友回復:
正因為這是一個有趣的問題,有幾個可能的解決方案,這里是另一種使用元編程的方法。
這個想法是我們df.remove變成一個運算式串列,然后我們filter(mydata, !!! .)通過將它與!!!運算子拼接在內部使用它。
獲取運算式串列的一種方法是使用rowwise summarise并創建一個list運算式,使用bquote它可以評估包含在.(). 在我們的例子中,min和max值。
雖然這是可能的,但我可能會使用@ekoam 的 {data.table} 或@Ronak 的基本 R 方法。
library(dplyr)
df.remove %>%
rowwise %>%
summarise(x = list(bquote(!x %in% c(.(min):.(max))))) %>%
pull(x) %>%
filter(mydata, !!! .)
#> `summarise()` has ungrouped output. You can override using the `.groups`
#> argument.
#> x y
#> 1 1 26
#> 2 2 27
#> 3 7 32
#> 4 8 33
#> 5 9 34
#> 6 14 39
#> 7 15 40
#> 8 16 41
#> 9 21 46
#> 10 25 50
由reprex 包(v0.3.0)于 2022-01-23 創建
uj5u.com熱心網友回復:
使用data.table::inrange.
library(data.table)
mydata[!mydata$x %inrange% df.remove, ]
# x y
# 1 1 26
# 2 2 27
# 7 7 32
# 8 8 33
# 9 9 34
# 14 14 39
# 15 15 40
# 16 16 41
# 21 21 46
# 25 25 50
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/420151.html
標籤:
