Измените значение столбца в R на основе значений двух других столбцов - PullRequest
1 голос
/ 07 августа 2020

Я пытаюсь изменить значение одного столбца на основе значений двух других столбцов. Пока что это вызывает у меня головную боль, и я не уверен, возможно ли это вообще.

Мой набор данных выглядит так. Один столбец - это время, а два других столбца отражают родительские отношения потомка. В странных случаях, например, в момент времени 1, у меня есть потомок "D", который появляется впервые в наборе данных, и его не было в предыдущий момент времени, чтобы служить одновременно и потомством, и отцом. время.

Данные

structure(list(time = c(0L, 0L, 0L, 1L, 1L, 1L, 2L, 2L, 2L), 
    offspring = c("A", "B", "C", "A", "D", "E", "A", "F", "G"
    ), parent = c(NA, NA, NA, "A", "B", "D", "A", "A", "F")), class = "data.frame", row.names = c(NA, 
-9L))

то, что мне нужно, это

  1. , чтобы найти все существующие потомки в единовременной точке, но не в предыдущей (без учета временной точки 0) и служат как потомком, так и отцом, как D и F

  2. Когда я их нахожу, я хотел бы уменьшить один точный момент времени на 0,5

time  offspring  parent
 0       A        NA
 0       B        NA
 0       C        NA
 1       A        A
 0.5     D        B 
 1       E        D
 2       A        A
 1.5     F        A
 2       G        F

Любая помощь или руководство по этому вопросу были бы очень признательны.

Ответы [ 3 ]

1 голос
/ 07 августа 2020

Создайте 2 фрейма данных, обнаруживая первые появления каждого животного как в качестве родителя, так и в качестве потомка. Найдите время и животных, встречающихся в обоих столбцах комбайнов, а затем обновите время в исходном фрейме данных.

df <-structure(list(time = c(0L, 0L, 0L, 1L, 1L, 1L, 2L, 2L, 2L), 
                    offspring = c("A", "B", "C", "A", "D", "E", "A", "F", "G"), 
                    parent = c(NA, NA, NA, "A", "B", "D", "A", "A", "F")), class = "data.frame", 
                    row.names = c(NA, -9L))


library(dplyr)
#find the row where each Letter First appears as both a parent and offspring 
parents <-df %>% filter(complete.cases(.)) %>% group_by(parent) %>% slice(1) %>% select(time, parent)
offsprings <- df  %>% group_by(offspring) %>% slice(1) %>% select(time, offspring)

combined <- full_join(offsprings, parents)
#rows where the names match for both parent and offspring
matchingrows <-which(combined$parent == combined$offspring)

#update the times
for (i in matchingrows){
   row = which(df$time == combined$time[i] & df$offspring == combined$offspring[i])
   df$time[row] <- df$time[row] - 0.5
}
df
0 голосов
/ 07 августа 2020

Мое решение, вероятно, не самое краткое, но мне удалось заставить его работать, и его можно обобщить для большего набора данных. Я уверен, что есть способы улучшить это, поэтому мне любопытно посмотреть, что придумают другие. Сначала у меня были проблемы с индексами 0, поэтому я добавил 2 два столбца времени, который я вычел обратно в конце.

Идея в том, что я перебираю строки и нахожу потомков в текущем год (после года 0), но не предыдущий год. Затем я проверяю, кто из этих людей также был родителями в текущем году. Я компилирую строки, которые были потомками этих особей в тот период времени, в вектор, потому что мы удалим их позже. Затем я создаю новую строку с временем-0,5, этим потомком и его родителем. Я компилирую их в новый фрейм данных, который заменяет удаляемые строки.

Поскольку существует дублирование для каждой временной отметки, я делаю вектор строк для удаления и df строк для добавления уникальным. Затем я делаю удаления и добавления в исходный фрейм данных и согласовываю типы данных.

0 голосов
/ 07 августа 2020

В data.table, если хотите:

library(data.table)

DT <- data.table(time = c(0,0,0,1,1,1,2,2,2),
                 offspring = c('A', 'B', 'C', 'A', 'D', 'E', 'A', 'F', 'G'),
                 parent = c(NA, NA, NA, 'A', 'B', 'D', 'A', 'A', 'F'))

for (i in seq_len(nrow(DT))) {
  DT[i, time := fifelse(time != 0 & offspring %chin% DT[, parent] & !(offspring %chin% DT[seq_len(i-1), offspring]),
                        time - 0.5,
                        time)]
}

> DT
   time offspring parent
1:  0.0         A   <NA>
2:  0.0         B   <NA>
3:  0.0         C   <NA>
4:  1.0         A      A
5:  0.5         D      B
6:  1.0         E      D
7:  2.0         A      A
8:  1.5         F      A
9:  2.0         G      F

с dplyr:

library(dplyr)
library(tibble)

tbl <- tibble(time = c(0,0,0,1,1,1,2,2,2),
              offspring = c('A', 'B', 'C', 'A', 'D', 'E', 'A', 'F', 'G'),
              parent = c(NA, NA, NA, 'A', 'B', 'D', 'A', 'A', 'F'))

for (i in seq_len(nrow(tbl))) {
  tbl[i,][['time']] <- tbl[i, ] %>% mutate(time = if_else(time != 0 &
                                         offspring %in% tbl[['parent']] &
                                         !(offspring %in% tbl[seq_len(i-1),][['offspring']]),
                                       time - 0.5,
                                       time)) %>% pull(time)
}

> tbl
# A tibble: 9 x 3
   time offspring parent
  <dbl> <chr>     <chr> 
1   0   A         NA    
2   0   B         NA    
3   0   C         NA    
4   1   A         A     
5   0.5 D         B     
6   1   E         D     
7   2   A         A     
8   1.5 F         A     
9   2   G         F   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...