корректировка значения столбца на основе дублирующейся строки - итеративно R - PullRequest
0 голосов
/ 27 сентября 2018

Скажем, у меня есть этот набор данных:

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

Проблема здесь в том, что у нас все еще есть повторяющиеся значения egrow 3 и 4 (то, что они отличаются в столбце 'val', не имеет значения).Строки 10 и 11 имеют ту же проблему.Строки 5 и 6 в порядке.

Есть ли способ сделать это итеративно - т.е. добавить 0,1 к первому дубликату, 0,2 ко второму дубликату (с тем же значением времени) и т. Д. Таким образом, строка 4 станет 101,2, истрока 11 станет 109,2.Число дубликатов на значение неизвестно, но никогда не будет равно 10 (обычно максимум 4).

Ответы [ 3 ]

0 голосов
/ 27 сентября 2018

Как и в верхнем ответе на связанный вопрос , связанный @Henrik, здесь используется 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
0 голосов
/ 27 сентября 2018

С dplyr:

library(dplyr)

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

или с row_number() (предложено Хенриком):

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
0 голосов
/ 27 сентября 2018

Вот решение с одной строкой, использующее 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...