[英]Conditional sorting / reordering of column values in R
我有一個類似於以下的數據集,其中包含1列60行:
value
1 0.0423
2 0.0388
3 0.0386
4 0.0342
5 0.0296
6 0.0276
7 0.0246
8 0.0239
9 0.0234
10 0.0214
.
40 0.1424
.
60 -0.0312
我想對行進行重新排序,以便滿足某些條件。 例如,一個條件可能是: sum(df$value[4:7]) > 0.1000
& sum(df$value[4:7]) <0.1100
例如,數據集如下所示。
value
1 0.0423
2 0.0388
3 0.0386
4 0.1312
5 -0.0312
6 0.0276
7 0.0246
8 0.0239
9 0.0234
10 0.0214
.
.
.
60 0.0342
我嘗試使用repeat
和sample
,如下所示:
repeat{
df1 <- as_tibble(sample(sdf$value, replace = TRUE))
if (sum(df$value[4:7]) > 0.1000 & sum(df$value[4:7]) <0.1100) break
}
不幸的是,這種方法需要花費很多時間,我想知道是否有一種更快的方法可以基於諸如sum
或prod
數學條件對行進行重新排序
這是我在評論中概述的爬山方法的快速實現。 盡管必須在檢查所有條件都得到滿足時仍可以使用精確的條件,但我還是必須將所需的條件略微改組為“ sum(x[4:7])
從0.105的距離”。 好處是您可以輕松地為距離功能添加額外條件。
# Using same example data as Jon Spring
set.seed(42)
vs = rnorm(60, 0.05, 0.08)
get_distance = function(x) {
distance = abs(sum(x[4:7]) - 0.105)
# Add to the distance with further conditions if needed
distance
}
max_attempts = 10000
best_distance = Inf
swaps_made = 0
for (step in 1:max_attempts) {
# Copy the vector and swap two random values
new_vs = vs
swap_inds = sample.int(length(vs), 2, replace = FALSE)
new_vs[swap_inds] = rev(new_vs[swap_inds])
# Keep the new vector if the distance has improved
new_distance = get_distance(new_vs)
if (new_distance < best_distance) {
vs = new_vs
best_distance = new_distance
swaps_made = swaps_made + 1
}
complete = (sum(vs[4:7]) < 0.11) & (sum(vs[4:7]) > 0.1)
if (complete) {
print(paste0("Solution found in ", step, " steps"))
break
}
}
sum(vs[4:7])
不能真正保證此方法能夠解決問題,但是當我不確定是否有解決問題的“智能”方法時,我經常嘗試這種基本的爬坡方法。
下面是使用的方法combn
從基R,並且然后使用過濾dplyr
。 (我確定有一種方法可以解決,但我的基本功還沒有。)
60個池中只有4個數字,因此只有488k個不同的組合(忽略順序; = 60 * 59 * 58 * 57/4/3/2),因此可以在大約一秒鍾內快速蠻力。
# Make a vector of 60 numbers like your example
set.seed(42)
my_nums <- rnorm(60, 0.05, 0.08);
all_combos <- combn(my_nums, 4) # Get all unique combos of 4 numbers
library(tidyverse)
combos_table <- all_combos %>%
t() %>%
as_tibble() %>%
mutate(sum = V1 + V2 + V3 + V4) %>%
filter(sum > 0.1, sum < 0.11)
> combos_table
# A tibble: 8,989 x 5
V1 V2 V3 V4 sum
<dbl> <dbl> <dbl> <dbl> <dbl>
1 0.160 0.00482 0.0791 -0.143 0.100
2 0.160 0.00482 0.101 -0.163 0.103
3 0.160 0.00482 0.0823 -0.145 0.102
4 0.160 0.00482 0.0823 -0.143 0.104
5 0.160 0.00482 -0.0611 -0.00120 0.102
6 0.160 0.00482 -0.0611 0.00129 0.105
7 0.160 0.00482 0.0277 -0.0911 0.101
8 0.160 0.00482 0.0277 -0.0874 0.105
9 0.160 0.00482 0.101 -0.163 0.103
10 0.160 0.00482 0.0273 -0.0911 0.101
# … with 8,979 more rows
這表示在此示例中,我的序列中約有9000個不同的4個數字集符合標准。 我們可以選擇其中任何一個並將其放置在4-7位,以滿足您的要求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.