расчет суммы на основе общепринятых правил во фрейме данных - PullRequest
0 голосов
/ 31 октября 2018

Предпочтительно использовать data.table в R: я хочу вычислить сумму DIAM по ID, CYCLE # на основе следующих правил:

  1. если любой из DIAM для конкретного предметного цикла представлен как NE, то SUM не может быть вычислено (должно возвращаться NA)
  2. , если какой-либо из DIAM представлен как NA, тогда вычислите сумму, игнорируя NA (то есть, как будто это 0)
  3. если ни один не равен NA, то рассчитать сумму как обычно

Также я хотел бы заменить CYCLE число на числовое значение с BASELINE, представляющим 0.

dfin <- 
ID    CYCLE     NUM   DIAM
1     BASELINE  1      8
1     BASLEINE  2      4
1     CYCLE 1   1      6
1     CYCLE 1   2      2
1     CYCLE 2   1      6
1     CYCLE 2   2      NE
1     CYCLE 3   1      6
1     CYCLE 3   2      NA

dfout <- 
ID    CYCLE     SUM
1     0         12
1     1         8
1     2         NA
1     3         6

Это необходимо применять для каждого предмета. Там много циклов, но это только пример.

Ответы [ 2 ]

0 голосов
/ 31 октября 2018
# Data created
dfin<-data.table("ID" = rep(x = 1,times = 8),"CYCLE" = c("BASELINE","BASELINE","CYCLE 1","CYCLE 1","CYCLE 2","CYCLE 2","CYCLE 3","CYCLE 3"),
                 "NUM" = rep(x = c(1,2),times = 4),"DIAM" = c(8,4,6,2,6,"NE",6,NA))

# CYCLE transformed
dfin[,CYCLE := as.numeric(ifelse(CYCLE == "BASELINE","0",
                     substr(x = CYCLE,start = 7,stop = 7)))]

# SUM computed
dfin2<-dfin[,.(SUM = if(CYCLE == 0){
  NA_real_
} else if("NE" %in% DIAM){
  NA_real_
} else {
  sum(as.numeric(DIAM),na.rm = T)
}),by = c("ID","CYCLE")]

# IDs with CYCLE = 0 present have SUM updated to NA 
dfin2[ID %in% ID[which(CYCLE == 0)],SUM := NA]

Надеюсь, это поможет!

0 голосов
/ 31 октября 2018

Вот один из вариантов. Сгруппированные по 'ID' и match ed индекса 'CYCLE' (как показано в ожидаемом выводе), измените значения "DIAM" на NA, если any из "DIAM" имеет "NE", то summarise, взяв sum из 'DIAM', убедившись, что если все значения NA, верните NA

library(tidyverse)
dfin %>% 
  group_by(ID, CYCLE = match(CYCLE, unique(CYCLE))-1) %>% 
  mutate(DIAM = as.numeric(replace(DIAM, any(DIAM== "NE"), NA))) %>%
  summarise(SUM = NA^all(is.na(DIAM)) * sum(DIAM, na.rm = TRUE))
# A tibble: 4 x 3
# Groups:   ID [?]
#     ID CYCLE   SUM
#  <int> <dbl> <dbl>
#1     1     0    12
#2     1     1     8
#3     1     2    NA
#4     1     3     6

Или используйте условие if/else после шага group_by

dfin %>%
  group_by(ID, CYCLE = match(CYCLE, unique(CYCLE))-1)  %>% 
  summarise(SUM = if("NE" %in% DIAM) NA else sum(as.numeric(DIAM), na.rm = TRUE))

Или используя ту же логику с data.table

library(data.table)
setDT(dfin)[, .(SUM = if("NE" %in% DIAM) NA_real_ else 
   sum(as.numeric(DIAM), na.rm = TRUE)), .(ID, CYCLE = rleid(CYCLE)-1)]
#   ID CYCLE SUM
#1:  1     0  12
#2:  1     1   8
#3:  1     2  NA
#4:  1     3   6
* * Данные тысяча двадцать-один
dfin <- structure(list(ID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), 
  CYCLE = c("BASELINE", 
 "BASELINE", "CYCLE 1", "CYCLE 1", "CYCLE 2", "CYCLE 2", "CYCLE 3", 
 "CYCLE 3"), NUM = c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L), DIAM = c("8", 
 "4", "6", "2", "6", "NE", "6", NA)), row.names = c(NA, -8L), 
 class = "data.frame")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...