我有一个类似于以下的数据集,具有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
答案 0 :(得分:2)
这是我在评论中概述的爬山方法的快速实现。我必须将所需条件略微改组为“ 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])
不能真正保证此方法能够解决问题,但是当我不确定是否有解决问题的“智能”方法时,我经常尝试这种基本的爬坡方式。
答案 1 :(得分:1)
这是一种使用基数R中的combn
,然后使用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位,以满足您的要求。