簡體   English   中英

數數。 R中每組按順序連續出現

[英]Count number of. consecutive occurrences in sequence per group in R

我有一個輕微的程序問題,我似乎無法弄清楚。 我想知道如何以優雅的方式計算從 r 中每組的不同值開始的序列中連續數字的數量

例如,我們有一個帶有名稱和數字的數據框,並希望找到最小化數據框,每個名稱只保留 1 個條目,另一個是每個名稱的連續條目數

names <- c(rep("bob",5), rep("henry",5), rep("maria",5))
goals <- c(1,2,3,5,4, 4,3,4,5,2, 1,2,4,6,5)
input.df <- data.frame(names, goals)

所以從 1 開始,輸出數據框會像下面的那樣,其中“bob”有一個 3,因為他的目標是從 1 到 3 個連續的目標條目,亨利有 0,因為他沒有 1 或任何有序條目和瑪麗亞有 2 個因為她有從 1 到 2 的條目

names <- c("bob", "henry", "maria")
runs <- c("3", "0", "2")
output.df.from.1 <- data.frame(names, goals)

從 3 開始,bob 和 maria 都是 0,但 henry 現在是 3,因為他有 3、4、5。

names <- c("bob", "henry", "maria")
runs <- c("0", "3", "0")
output.df.from.3 <- data.frame(names, goals)

我確信必須有一個簡單的解決方案,但我找不到任何解決方案,但是我可能正在尋找錯誤的東西。

有人有建議嗎?

這是您的答案的可能解決方案。 思路是1)先找出每個人的(多個)連續數字,然后2)給定一個值,從該值開始找出連續數字的長度。

考慮到每個人可以有多個連續數字的情況,我稍微更改了您的示例數據。 (例如,bob 現在有數字 1、2、3、5、4、7、8、9,連續的組是 1、2、3 和 7、8、9)。

  1. 找出每個人的連續數字。 通過第一組names ,每個組內,發現的以前和未來的數字goals 如果它是連續的,那么previous_goal - current_goal = -1next_goal - current_goal = 1 注意我同時使用上一個/下一個以保留連續組中的所有值。
library(tidyverse)
names <- c(rep("bob",8), rep("henry",5), rep("maria",5))
goals <- c(1,2,3,5,4, 7,8,9, 4,3,4,5,2, 1,2,4,6,5)
df1 <- data.frame(names, goals) 

df2 <- df1 %>% 
  group_by(names) %>%  
  mutate(goals_lag = lag(goals) - goals) %>% 
  mutate(goals_lead = lead(goals) - goals) %>% 
  filter(goals_lag == -1 | goals_lead == 1) %>% 
  select(-goals_lag, -goals_lead)
  1. 編寫一個函數來計算從給定值開始的連續數字的長度。 在 bob 的情況下,有兩個連續的組 1、2、3 和 7、8、9。 如果給定的值為 1,那么長度應該是 3 而不是 6。因此我們需要知道不同連續組的起始位置在哪里(組 7、8、9 的起始索引為 4)。 定位到給定值的位置后(如果給定值為1,則索引為1),我們可以使用下一組的起始位置減去給定值位置(在這種情況下為4-1=3),就是這樣計算長度)。
cons_len <- function(df, name, start_val){
  
# take goals as a vector
  vec <- (df %>% filter(names == name))$goals
# find the starting positions of different groups
  vec_stops <- which( (vec - c(vec[1] - 1, vec[-length(vec)])) != 1)
# find the index of the given value
  vec_start <- which(vec == start_val)
  
# if not find the value, return 0
  if (length(vec_start)==0) {
    return(0)
    
# if there is only one group of consecutive numbers
  } else if (length(vec_stops) == 0) {
    return(length(vec) - vec_start + 1)
    
  } else {
   
# if there are multiple groups of consecutive numbers
    len <- vec_stops[vec_start <= vec_stops][1] - vec_start
    return(ifelse(len == 1, 0, len))
  }
}

# apply to each name
sapply(unique(df1$names), function(name) cons_len(df2, name, 1))
# bob henry maria 
# 3     0     2 

sapply(unique(df1$names), function(name) cons_len(df2, name, 3))
# bob henry maria 
# 0     3     0 

暫無
暫無

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

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