R中一列的子集数据帧具有相同的差异

时间:2018-03-13 21:34:56

标签: r dataframe diff

我正在尝试迭代数据帧(数据)中的行以检查其中一列(数据$ ID)在连续元素之间是否具有相似的差异(例如,3)。如果是,请保留行,否则删除行。棘手的部分是我需要在删除某一行后重新比较连续的元素。

data <- data.frame(ID=c(3.1, 6, 6.9, 9, 10.5, 12, 14.2, 15),
                   score = c(70, 80, 90, 65, 43, 78, 44, 92))
data
    ID    score
1   3.1     70
2   6     80
3   6.9     90
4   9     65
5   10.5    43
6   12    78
7   14.2    44
8   15    92

for (i in (length(data$ID)-1)) {
    first <- data$ID[i]
    second <- data$ID[i+1]
    if ((second-first) == 3){
       data <- data[-(i+1),]
    }    
 }

预期的输出数据应为

    ID    score
1   3.1     70
2   6     80
3   9     65
4   12    78
5   15    92

由于差异不同,排除了第3,5,7行。但我的代码失败了。

我也尝试使用diff功能,

DF <- diff(data)

但它没有注意这样一个事实,即删除一行后,差异将会改变。我应该在循环中使用diff函数,但数据框是动态更改的。

3 个答案:

答案 0 :(得分:2)

使用递归函数(调用自身的函数)

data <- data.frame(ID=c(3.1, 6, 6.9, 9, 10.5, 12, 14.2, 15),
                   score = c(70, 80, 90, 65, 43, 78, 44, 92))

# use recursive function to trim the remainder of the list
trim_ids <- function (ids) {
  # if only one element, return it
  if (length(ids) <= 1) {
    return(ids) 
  }
   # if the gap between element 2 and element 1 is small enough 
  if ((ids[2] - ids[1]) < 2.9 ) {
    # trim after dropping the second element
    return(trim_ids(ids[-2])) 
  } else {
    # keep the first element and trim from the second element
    return(c(ids[1], trim_ids(ids[2:length(ids)] )))
  }
}

# find the ids to keep
keep_ids <- trim_ids(data$ID)

# select the matching rows
data[data$ID %in% keep_ids,]

#      ID score
# 1  3.1    70
# 2  6.0    80
# 4  9.0    65
# 6 12.0    78
# 8 15.0    92

答案 1 :(得分:2)

可以使用cumsumdiff作为选项来实现选项:

#data
data <- data.frame(ID=c(3.1, 6, 6.9, 9, 10.5, 12, 14.2, 15),
                   score = c(70, 80, 90, 65, 43, 78, 44, 92))


data[c(0, cumsum(diff(round(data$ID))) %% 3 ) == 0,]

# ID score
# 1  3.1    70
# 2  6.0    80
# 4  9.0    65
# 6 12.0    78
# 8 15.0    92

答案 2 :(得分:0)

如果您定义要保留ID的所有行,当舍入为0位数时,属于3的乘积,您可以尝试:

 df1 <- data.frame(ID=c(3.1, 6, 6.9, 9, 10.5, 12, 14.2, 15),
               score = c(70, 80, 90, 65, 43, 78, 44, 92))


df1[round(df1$ID) %% 3 == 0,]

ID score
1  3.1    70
2  6.0    80
4  9.0    65
6 12.0    78
8 15.0    92