簡體   English   中英

R中列值的條件排序/重新排序

[英]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.1000sum(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

我嘗試使用repeatsample ,如下所示:

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
    }

不幸的是,這種方法需要花費很多時間,我想知道是否有一種更快的方法可以基於諸如sumprod數學條件對行進行重新排序

這是我在評論中概述的爬山方法的快速實現。 盡管必須在檢查所有條件都得到滿足時仍可以使用精確的條件,但我還是必須將所需的條件略微改組為“ 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM