Операция Data.Table из одного фрейма данных в другой - PullRequest
1 голос
/ 20 февраля 2020
dataWANT=data.frame("student"=c(1,2,3,4,5),
                    "w1"=c(2,2,0,2,1),
                    "w2"=c(2,0,0,2,1),
                    "w3"=c(2,2,0,2,1),
                    "w4"=c(1,0,0,1,2))


dataHAVE=data.frame("student"=c(1,2,3,4,5),
                    "f1"=c(0,0,0,1,1),
                    "c1"=c(1,1,0,1,0),
                    "f2"=c(1,0,0,0,1),
                    "c2"=c(1,0,0,1,0),
                    "f3"=c(0,0,0,1,1),
                    "c3"=c(1,1,0,1,0),
                    "f4"=c(1,0,0,0,1),
                    "c4"=c(NA,0,0,1,0))

У меня есть «dataHAVE», и я пытаюсь сгенерировать «dataWANT». Правила:

, если f1 и c1 = 0, w1 = 0

, если f1 = 1 и c1 = 0, w1 = 1

, если f1 = 0 и c1 = 1, w1 = 2

, если f1 = 1 и c1 = 1, w1 = 2

По сути, мне интересно: как я могу сгенерировать эти переменные, и, во-вторых, как я могу выполнить функцию data.table для dataHAVE, помещая новые переменные в dataWANT?

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Мы можем использовать pivot_longer/pivot_wider

library(dplyr)
library(tidyr)
library(stringr)
dataHAVE %>%
  pivot_longer(cols = -student, names_to = c(".value", "grp"), 
        names_sep="(?<=[fc])(?=\\d+)") %>% 
  group_by(student, grp= str_c('w', grp)) %>% 
  transmute(w =  case_when(f %in%  0:1 & c == 1 ~ 2, 
            f == 1 & c == 0 ~ 1, TRUE ~ 0)) %>% 
  pivot_wider(names_from = grp, values_from = w)

С data.table мы можем использовать fcase (из версии devel) вместе с melt/dcast

library(data.table)
dM <- melt(setDT(dataHAVE), measure = patterns("^f", "^c"), 
  value.name = c('f', 'c'))[, w := fcase(f %in% 0:1 & c== ~ 2, 
      f == 1 & c == 0 ~ 1, TRUE ~ 0)]
dcast(dM, student ~ paste0('w', variable), value.var = 'w')
0 голосов
/ 20 февраля 2020

Это работает, но вроде как «грязно» из-за двух повторяющихся столбцов в dataHAVE. Чтобы решить эту проблему, я просто запускаю команду для удаления исходных столбцов дважды ...: D

Я также изменил вашу исходную команду dataHAVE, чтобы создать data.table вместо data.frame для использования data.table логи c.

Это не совсем элегантно, но, по крайней мере, работает. Остальное - просто создание правил логики c перед удалением старых столбцов, я просто включил правила, перечисленные в вашем ответе.

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

РЕДАКТИРОВАТЬ: новая версия, которая извлекает dataWANT используя имена столбцов и с = FALSE. Гораздо чище:)

library(data.table)
dataHAVE=data.table("student"=c(1,2,3,4,5),
                    "f1"=c(0,0,0,1,1),
                    "c1"=c(1,1,0,1,0),
                    "f2"=c(1,0,0,0,1),
                    "c2"=c(1,0,0,1,0),
                    "f3"=c(0,0,0,1,1),
                    "c4"=c(1,1,0,1,0),
                    "f4"=c(1,0,0,0,1),
                    "c4"=c(NA,0,0,1,0))

old_columns <- colnames(dataHAVE)[2:ncol(dataHAVE)]

dataHAVE[f1 == 0 & c1 == 0, 'w1' := 0]
dataHAVE[f1 == 1 & c1 == 0, 'w1' := 1]
dataHAVE[f1 == 0 & c1 == 1, 'w1' := 2]
dataHAVE[f1 == 1 & c1 == 1, 'w1' := 2]

keep_columns <- setdiff(colnames(dataHAVE), old_columns)

dataWANT <- dataHAVE[, keep_columns, with = FALSE]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...