Скомпилировать данные для того же идентификатора - PullRequest
0 голосов
/ 07 августа 2020

Я хочу скомпилировать этот фрейм данных в фрейм данных только с одной строкой для каждого идентификатора, для каждого столбца value1, value2, value3, я хочу взять значение для A- B. Я попытался сделать a для l oop, чтобы перебрать идентификаторы, но я не знаю, как продолжить, какие-нибудь советы? Было бы действительно полезно, если бы функция запускала множество столбцов, это всего лишь пример трех столбцов. Спасибо!

df <- data.frame(
   id=rep(1:5,each=2),
   trt = rep(c("A","B","A","B", "B","A", "B","A","A","B"),),
   value1 = sample(1:100,10),
   value2 = sample(1:100,10),
   value3 = sample(1:100,10),
   stringsAsFactors = F)
> df
   id trt value1 value2 value3
   1   A     98     64     91
   1   B     64     48     16
   2   A     26     31     87
   2   B     93     62     24
   3   B     32     37     71
   3   A     83      6     92
   4   B     82     68     36
   4   A     30      5     66
   5   A     87     29     48
   5   B     86     47     82
 
for (i in length(id)) {
     d <- df[df$id==i,]
     d$value1[d$trt=="A"]- d$value1[d$trt=="B"]
     print(i)
     }

Ответы [ 3 ]

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

Вот базовое решение R со стратегией split/lapply/combine. См. статью Хэдли Уикхема .

cols <- grep("value", names(df), value = TRUE)
sp <- split(df[c("trt", cols)], df$id)
res <- lapply(seq_along(sp), function(i){
  X <- sp[[i]][order(sp[[i]]$trt), ]
  Y <- X[1, cols] - X[2, cols]
  cbind(data.frame(id = names(sp)[i]), Y)
})
res <- do.call(rbind, res)

res
#  id value1 value2 value3
#1  1     -6     63     28
#3  2    -32      8    -18
#6  3      6     -7    -63
#8  4    -67    -45      2
#9  5      1     20     45
1 голос
/ 07 августа 2020

Вы также можете попробовать пакет data.table (используя те же воспроизводимые данные, что и @Edo):

library(data.table)
setDT(df, key = c("id","trt"))
df[, lapply(.SD, function(x) diff(x) * -1), by = id, .SDcols = -2]

Результат:

   id value1 value2 value3
1:  1    -16     17    -58
2:  2    -49     23    -55
3:  3     82     48    -18
4:  4    -23      9     13
5:  5    -18    -79     -7

В качестве альтернативы вы можете также делаем:

library(data.table)
setorder(df, id, -trt)
setDT(df)[, lapply(.SD, diff), by = id, .SDcols = -2]
1 голос
/ 07 августа 2020

Ваши данные:

set.seed(42)
df <- data.frame(
    id=rep(1:5,each=2),
    trt = rep(c("A","B","A","B", "B","A", "B","A","A","B"),),
    value1 = sample(1:100,10),
    value2 = sample(1:100,10),
    value3 = sample(1:100,10),
    stringsAsFactors = F)

Решение:

library(tidyr)
library(dplyr)

df %>% 
    gather(key, value, -trt, -id) %>% 
    mutate(value = if_else(trt == "B", -value, value)) %>% 
    group_by(id, key) %>% 
    summarise(value = sum(value)) %>% 
    ungroup() %>% 
    spread(key, value)

Дело здесь в том, чтобы сначала преобразовать с помощью gather фрейм данных в длинную форму и поместить все ваше значение в одном столбце.

Видно, что значения с B должны быть вычтены, я установил значения с B как отрицательные.

В этот момент я свободен для некоторых всех значений id и key (что соответствует метке value1, value2, value3).

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

Неважно, сколько столбцов «valueN» у вас есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...