根据是否重复行调整列的值-迭代R

时间:2018-09-27 16:49:14

标签: r

说我有这个数据集:

df <- data.frame(time = c(100, 101, 101, 101, 102, 102, 103, 105, 109, 109, 109),
           val = c(1,3,1,2,3,1,2,3,1,2,1))

df

   time val
1   100   1
2   101   3
3   101   1
4   101   2
5   102   3
6   102   1
7   103   2
8   105   3
9   109   1
10  109   2
11  109   1

我们可以在“时间”列中标识重复的时间,如下所示:

df[duplicated(df$time),]

我想要做的是调整时间值(加0.1)(如果重复的话)。我可以这样:

df$time <- ifelse(duplicated(df$time),df$time+.1,df$time)

   time val
1  100.0   1
2  101.0   3
3  101.1   1
4  101.1   2
5  102.0   3
6  102.1   1
7  103.0   2
8  105.0   3
9  109.0   1
10 109.1   2
11 109.1   1

这里的问题是我们仍然有重复的值,例如第3行和第4行(它们在“ val”列中的不同无关紧要)。第10和11行有相同的问题。第5和第6行很好。

是否有一种迭代的方式-即将0.1添加到第一副本,将0.2添加到第二副本(具有相同的时间值),以此类推。这样,第4行将变为101.2,第11行将变为109.2。每个值重复的次数是未知的,但绝不会等于10(通常是最多4)。

3 个答案:

答案 0 :(得分:1)

与@Henrik链接的related question的最高答案一样,它使用data.table::rowid

library(data.table)
setDT(df)

df[, time := time + 0.1*(rowid(time) - 1)]

#      time val
#  1: 100.0   1
#  2: 101.0   3
#  3: 101.1   1
#  4: 101.2   2
#  5: 102.0   3
#  6: 102.1   1
#  7: 103.0   2
#  8: 105.0   3
#  9: 109.0   1
# 10: 109.1   2
# 11: 109.2   1

答案 1 :(得分:0)

这是使用base R的单行解决方案-

df <- data.frame(time = c(100, 101, 101, 101, 102, 102, 103, 105, 109, 109, 109),
           val = c(1,3,1,2,3,1,2,3,1,2,1))
df$new_time <- df$time + duplicated(df$time)*0.1*(ave(seq_len(nrow(df)), df$time, FUN = seq_along) - 1)
df
#    time val new_time
# 1   100   1    100.0
# 2   101   3    101.0
# 3   101   1    101.1
# 4   101   2    101.2
# 5   102   3    102.0
# 6   102   1    102.1
# 7   103   2    103.0
# 8   105   3    105.0
# 9   109   1    109.0
# 10  109   2    109.1
# 11  109   1    109.2

答案 2 :(得分:0)

使用dplyr

library(dplyr)

df %>%
  group_by(time1 = time) %>%
  mutate(time = time + (0:(n()-1))*0.1) %>%
  ungroup() %>%
  select(-time1)

或使用row_number()(由Henrik建议):

df %>%
  group_by(time1 = time) %>%
  mutate(time = time + (row_number()-1)*0.1) %>%
  ungroup() %>%
  select(-time1)

输出:

    time val
1  100.0   1
2  101.0   3
3  101.1   1
4  101.2   2
5  102.0   3
6  102.1   1
7  103.0   2
8  105.0   3
9  109.0   1
10 109.1   2
11 109.2   1