计算R df列中相等元素之间的不相等元素

时间:2018-08-09 12:05:52

标签: r dataframe

我对R还是很陌生,尽管我已经处理了一些数据,但我对如何解决这个问题完全不知所措。到目前为止,Google和SO搜索并没有帮助我。很抱歉,如果这是重复的,请为我指出正确的解决方案。

我有一个包含2列的df,分别称为id和seq。像这样

set.seed(12)
id <- rep(c(1:2),10)
seq<-sample(c(1:4),20,replace=T)
df <- data.frame(id,seq)
df <- df[order(df$id),]

    id seq  
 1   1   1
 3   1   4
 5   1   1
 7   1   1
 9   1   1
 11  1   2
 13  1   2
 15  1   2
 17  1   2
 19  1   3
 2   2   4
 4   2   2
 6   2   1
 8   2   3
 10  2   1
 12  2   4
 14  2   2
 16  2   2
 18  2   3
 20  2   1

我需要计算seq列中相等元素之间不相等元素的数量,例如1和1或3和3等之间有多少个元素。该元素的第一个实例应为NaN,因为在此之前没有要计数的元素。如果下一个元素相同,则应仅编码0,因为不存在不等式中间的元素,例如1和1。结果应写在新列中,例如延迟。

一个要注意的是,一旦在id列(此处为1和2)中开始了新的id,就必须重新开始此过程。

这就是我希望输出的内容:

     id seq   delay 
 1   1   1     NA
 3   1   4     NA
 5   1   1     1
 7   1   1     0
 9   1   1     0
 11  1   2     NA
 13  1   2     0
 15  1   2     0
 17  1   2     0
 19  1   3     NA
 2   2   4     NA
 4   2   2     NA
 6   2   1     NA
 8   2   3     NA
 10  2   1     1
 12  2   4     4
 14  2   2     4
 16  2   2     0
 18  2   3     4
 20  2   1     4

我真的希望有人能够帮助我解决这个问题,并让我了解更多有关此的信息。

4 个答案:

答案 0 :(得分:5)

一个简单的dplyr解决方案:

df %>%
  mutate(row = 1:n()) %>%
  group_by(id, seq) %>%
  mutate(delay = row - lag(row) - 1) %>%
  select(-row)
# # A tibble: 20 x 3
# # Groups:   id, seq [8]
#       id   seq delay
#    <int> <int> <dbl>
#  1     1     1    NA
#  2     1     4    NA
#  3     1     1     1
#  4     1     1     0
#  5     1     1     0
#  6     1     2    NA
#  7     1     2     0
#  8     1     2     0
#  9     1     2     0
# 10     1     3    NA
# 11     2     4    NA
# 12     2     2    NA
# 13     2     1    NA
# 14     2     3    NA
# 15     2     1     1
# 16     2     4     4
# 17     2     2     4
# 18     2     2     0
# 19     2     3     4
# 20     2     1     4

答案 1 :(得分:2)

这里有可能在dplyr链中使用自定义函数

my.function <- function(x) {
    ret <- rep(NA, length(x))
    for (i in 2:length(x)) {
        for (j in (i-1):1) {
            if (x[j] == x[i]) {
                ret[i] = i - j - 1
                break
            }
        }
    }
    return(ret)
}

library(dplyr)
df %>%
    group_by(id) %>%
    mutate(delay = my.function(seq))
## A tibble: 20 x 3
## Groups:   id [2]
#      id   seq delay
#   <int> <int> <dbl>
# 1     1     1   NA
# 2     1     4   NA
# 3     1     1    1.
# 4     1     1    0.
# 5     1     1    0.
# 6     1     2   NA
# 7     1     2    0.
# 8     1     2    0.
# 9     1     2    0.
#10     1     3   NA
#11     2     4   NA
#12     2     2   NA
#13     2     1   NA
#14     2     3   NA
#15     2     1    1.
#16     2     4    4.
#17     2     2    4.
#18     2     2    0.
#19     2     3    4.
#20     2     1    4.    

一些进一步的解释:

  1. 我们将行按id分组,然后将my.function应用于列seq中的条目。这样可以确保我们分别处理具有不同id的行。

  2. my.function接受数字条目的向量,检查先前的相等条目,并返回当前和先前的相等条目之间的距离减去一(即,计算两者之间的元素数)。

  3. my.function使用两个for循环,但这应该很快,因为我们不会动态地增长任何向量(ret已预先分配在{{1的开头}}),并且一旦遇到相等的元素,我们就会中断内部循环。

答案 2 :(得分:1)

尝试:

set.seed(12)
id <- rep(c(1:2),10)
seq<-sample(c(1:4),20,replace=T)
df <- data.frame(id,seq)
df <- df[order(df$id),]
df

get_lead <- function(x) {
  x <- as.character(x)
  l <- list(unique(x))
  res <- rep(NA, length(x))
  for (i in seq_along(x)) {
    if (!is.null(l[[x[i] ]])) {
      res[i] <- (i - l[[x[i] ]] - 1)
    }
    l[[x[i] ]] <- i
  }
  res
}
df$delay <- unlist(lapply(split(df$seq, df$id), get_lead))
df  

# id seq delay
#1   1   1    NA
#3   1   4    NA
#5   1   1     1
#7   1   1     0
#9   1   1     0
#11  1   2    NA
#13  1   2     0
#15  1   2     0
#17  1   2     0
#19  1   3    NA
#2   2   4    NA
#4   2   2    NA
#6   2   1    NA
#8   2   3    NA
#10  2   1     1
#12  2   4     4
#14  2   2     4
#16  2   2     0
#18  2   3     4
#20  2   1     4

答案 3 :(得分:0)

这是方法: -write函数查找哪一行从索引的第一行开始 -写入功能,可计算不同数字的数量与最新的重复数字 -将函数应用于所有行并分配给可变延迟

Indstart <- function(j,df){
  ind_start <- min(which(df[1:j,1]==df[j,1]))
}

difval <- function( j, df){
  i <- Indstart(j, df)
  pos_j_pr <- ifelse(length(which(df[i:(j-1),2]==df[j,2]))>0, max(which(df[i:(j-1),2]==df[j,2])) + i-1, 0)
  non_rep_num <- ifelse(pos_j_pr>0, sum(df[pos_j_pr:j,2] != df[j,2]), "NA")
  return(non_rep_num)
}

for (j in 1:length(df[,1])){
  df$delay[j] <- difval(j,df)
}