簡體   English   中英

R-查找正/負值的最大游程

[英]R - Find maximum run of positive / negative values

我有大約3000行的數據框。 我希望找到最長的正數和負數。

我的示例數據框:df

1   0.502310591 
2   -0.247577976    
3   -0.307256769    2
4   0.442253678 
5   -0.795770351    
6   2.08244648  
7   -0.01672777 
8   -0.164145656    2
9   0.610117365 
10  0.014758371 
11  0.381105476 
12  0.721386493 4
13  -0.363222383    
14  0.201409322 
15  0.724867214 
16  -1.586829584    
17  1.066288451 
18  0.182824494 
19  0.237447191 
20  -0.215475797

最長正向運行:4最長負向運行:2

我正在關注本教程: https : //ocw.mit.edu/ans7870/18/18.05/s14/html/r-tut-rle.html

我需要為值大於0且小於0的最長值提供資金。 那么有什么辦法可以編輯以上內容?

我猜這只能找到1,0的最長長度? 如果是這種情況,那么我將需要一個ifelse 1,0輔助列來拆分負數,正數……然后用此代碼找到最長的長度:

> df$wins <- ifelse(df$V2 > 0, 1, 0) 
> df$loss <- ifelse(df$V2 < 0, 1, 0)
> win <- (c(df$wins))
> max(rle(win)$lengths)
[1] 4

這適用於尋找最大的勝利...

這是損失:

> print(df$loss)
 [1] 0 1 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 1
> df$loss <- ifelse(df$V2 < 0, 1, 0)
> print(df$loss)
 [1] 0 1 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 1
> loss <- (c(df$loss))
> max(rle(loss)$lengths)
[1] 4

不知道為什么說4 ...最大損失顯然是2,有人知道為什么嗎? 我想念的是,勝利的邏輯對損失的作用不應該完全一樣嗎? 我看不到代碼中的任何錯誤...

如果df $ loss中的值小於0,則打印1否則為0。使包含df $ loss列內容的向量使用max(rle(loss)$lengths)再次找到最大長度為1的結果,即為4。顯然2?

我認為rle會根據您的目標完成工作,但是我將發布一種替代解決方案,其中包含更多的數據操作,但是您將可以獲得更多信息。

通常,回答一個問題后,您會被要求回答更多。 例如,了解正數與負數的游程分布,因為最大值可能不會告訴您多少。 或者,進行統計比較以查看陽性結果平均比陰性結果運行時間更長。

另外,在大約3000行的情況下,我認為您不會遇到任何速度問題。

library(dplyr)

# example dataset
dt = data.frame(x = c(1,-1,-2,0,2,4,3,5,-5,-6,-7,0,0))

# get a dataset that assigns an id to all positive or negative series
dt %>%
  mutate(sign = ifelse(x > 0, "pos", ifelse(x < 0, "neg", "zero")), # get the sign of the value
         sign_lag = lag(sign, default = sign[1]),       # get previous value (exception in the first place)
         change = ifelse(sign != sign_lag, 1 , 0),      # check if there's a change
         series_id = cumsum(change)+1) %>%              # create the series id
  print() -> dt2                                        # print to screen and save it

#     x sign sign_lag change series_id
# 1   1  pos      pos      0         1
# 2  -1  neg      pos      1         2
# 3  -2  neg      neg      0         2
# 4   0 zero      neg      1         3
# 5   2  pos     zero      1         4
# 6   4  pos      pos      0         4
# 7   3  pos      pos      0         4
# 8   5  pos      pos      0         4
# 9  -5  neg      pos      1         5
# 10 -6  neg      neg      0         5
# 11 -7  neg      neg      0         5
# 12  0 zero      neg      1         6
# 13  0 zero     zero      0         6

您可以刪除幫助列sign_lag並進行change因為我已將它們包括在內)只是為了演示該過程的工作方式。

# Get longest runs
dt2 %>% 
  count(sign, series_id) %>%
  group_by(sign) %>%
  filter(n == max(n)) %>%
  select(-series_id) %>%
  ungroup

# # A tibble: 3 x 2
#    sign     n
#   <chr> <int>
# 1   neg     3
# 2   pos     4
# 3  zero     2


# Get all runs
dt2 %>% count(sign, series_id)

# # A tibble: 6 x 3
#    sign series_id     n
#   <chr>     <dbl> <int>
# 1   neg         2     2
# 2   neg         5     3
# 3   pos         1     1
# 4   pos         4     4
# 5  zero         3     1
# 6  zero         6     2

如果獲得全部運行,您將能夠繪制正運行與負運行的分布圖,或進行統計比較以查看正運行的平均時間是否比負運行的平均時間長。

這是一種簡單的方法,我假設您從一個僅具有值的數據幀開始,我還假設您需要一個具有相同數字計數的數據幀,正數列運行,負數列運行。

set.seed(42)
df=data.frame(x= runif(300, -1.0, 1.0))
count_pos=c()
count_neg=c()
n1=df$x[1]
if (sign(n1)==1){
  count_pos[1]=1
  count_neg[1]=0
}else{
  count_neg[1]=1
  count_pos[1]=0
}
count=1
index=1
for (i in df$x[2:nrow(df)]){
  #print (i)
  index=index+1
  if (sign(n1)==sign(i)){
    count=count+1
  }
  else{
    count=1
  }
  if (sign(i)==1){
    count_pos[index]=count
    count_neg[index]=0
  }else{
    count_pos[index]=0
    count_neg[index]=count
  }
  n1=i
}

df2=data.frame(x=df$x,count_pos=count_pos,count_neg=count_neg)
#df2 contains the dataframe with columns that count the run for numbers with 
#same sign
print (paste("Maximum run of Positive numbers:",max(count_pos)))
print (paste("Maximun run of negative numbers:",max(count_neg)))

我知道有一種更緊湊的方法可以執行此操作,但是此代碼可以解決問題。

為了在一系列得到最大的正/負運行(在一個data.frame中的一列的情況下, rle功能是所有您需要:

set.seed(123)
df <- data.frame(col1=rnorm(20, mean = 0, sd = 1))

最大。 pos運行:

max(rle(sign(df$col1))[[1]][rle(sign(df$col1))[[2]] == 1])
[1] 5

最大。 neg.run:

max(rle(sign(df$col1))[[1]][rle(sign(df$col1))[[2]] == -1])
[1] 3

讓我們檢查一下結果:

> df
          col1
1  -0.56047565
2  -0.23017749
3   1.55870831
4   0.07050839
5   0.12928774
6   1.71506499
7   0.46091621
8  -1.26506123
9  -0.68685285
10 -0.44566197
11  1.22408180
12  0.35981383
13  0.40077145
14  0.11068272
15 -0.55584113
16  1.78691314
17  0.49785048
18 -1.96661716
19  0.70135590
20 -0.47279141

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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