2016-10-06 1 views
0

В приведенной ниже data.frame образца:Melt 4 колонки в то время как 3, сочетающие эти две переменные столбцы

Date <- seq(as.Date("2016/9/1"), as.Date("2016/9/10"), "days") 
A <- sample(0:200, 10) 
B <- sample(0:400, 10) 
A_limit <- rep(200,10) 
B_limit <- rep(400,10) 
data_sample <- data.frame(Date,A,B,A_limit,B_limit) 

>  Date A B A_limit B_limit 
1 2016-09-01 175 270  200  400 
2 2016-09-02 160 50  200  400 
3 2016-09-03 173 25  200  400 
... 

и я хотел бы, чтобы изменить его в форме:

>  Date limit variable value 
1 2016-09-01 200  A 175 
2 2016-09-02 200  A 160 
3 2016-09-03 200  A 173 
... 
31 2016-09-01 400  B 270 
32 2016-09-02 400  B 50 
33 2016-09-03 400  B 25 
.... 

мне удается получить это сделано, но мне кажется, мой путь далеко к сложному:

library("reshape2") 
data_sample_2 <- data_sample %>% melt(id=c("Date","A","B")) 

levels(data_sample_2$variable) <- c(levels(data_sample_2$variable),"A","B") 
data_sample_2$variable[data_sample_2$variable == "A_limit"] <- as.factor("A") 
data_sample_2$variable[data_sample_2$variable == "B_limit"] <- as.factor("B") 

names(data_sample_2)[names(data_sample_2) == "value"] <- "limit" 
names(data_sample_2)[names(data_sample_2) == "variable"] <- "variable_1" 

data_sample_3 <- data_sample_2 %>% melt(id=c("Date","variable_1","limit")) 
data_sample_3 <- droplevels(data_sample_3) 
data_sample_4 <- data_sample_3[data_sample_3$variable_1 == data_sample_3$variable,] 

data_sample_4$variable_1 <- NULL 

Я только начал использовать reshape2 пакет поэтому, пожалуйста, дайте мне знать о любом способе, которым я могу улучшить это преобразование data.frame (независимо от того, насколько это очевидно).

+1

вы можете сделать 'col1 <-c (" A_limit "," B_limit "); col2 <- c ("A", "B") '; 'data.table :: melt (data_sample, measure = list (col1, col2), value.name = c (" limit "," value "))', если вы не против числовой переменной 'col_ col. – mtoto

+0

Я получаю эту ошибку, когда я пытаюсь выполнить код: 'Ошибка: измерять переменные, не найденные в данных: c (" A_limit "," B_limit "), c (" A "," B ")'. Любая подсказка, что пошло не так? – RandomDude

+1

конвертировать 'data_sample' в' data.table' first – mtoto

ответ

1

Вы можете сделать это с помощью базового R просто stack ИНГ все, т.е.

df1 <- data.frame(Date = data_sample$Date, limit = stack(data_sample[-(1:3)])[[1]], 
        variable = stack(data_sample[2:3])[[2]], 
        value = stack(data_sample[2:3])[[1]], 
            stringsAsFactors = FALSE) 

head(df1) 
#  Date limit variable value 
#1 2016-09-01 200 A  67 
#2 2016-09-02 200 A  100 
#3 2016-09-03 200 A  166 
#4 2016-09-04 200 A  116 
#5 2016-09-05 200 A  89 
#6 2016-09-06 200 A  138 

tail(df1) 
#   Date limit variable value 
#15 2016-09-05 400 B  208 
#16 2016-09-06 400 B  387 
#17 2016-09-07 400 B  125 
#18 2016-09-08 400 B  116 
#19 2016-09-09 400 B  120 
#20 2016-09-10 400 B  241 
+0

Мне нравится это решение! Есть ли способ, которым я могу напрямую указывать столбцы при укладке? – RandomDude

+0

@RandomDude updated – Sotos

+1

Я пропустил двойной '[[...]]' при выборе векторов. Большой ответ большое спасибо! – RandomDude

1

Это то, что вы хотите?

data_sample_2 <- melt(data_sample,id.vars=c("Date","A_limit","B_limit")) 
data_sample_2$limit<- ifelse(data_sample_2$variable=="A",data_sample_2$A_limit,data_sample_2$B_limit) 
data_sample_2[,c("Date","limit","variable","value")] 
1

Поскольку вы использовали reshape2 в вашем примере, это может вас заинтересовать, чтобы увидеть, как справиться с этим в (более обновлен) tidyverse setup.

Я повторю свой код поколения:

Date <- seq(as.Date("2016/9/1"), as.Date("2016/9/10"), "days") 
A <- sample(0:200, 10) 
B <- sample(0:400, 10) 
A_limit <- rep(200,10) 
B_limit <- rep(400,10) 
data_sample <- data.frame(Date,A,B,A_limit,B_limit) 

# Preview 
head(data_sample) 
#>   Date A B A_limit B_limit 
#> 1 2016-09-01 39 53  200  400 
#> 2 2016-09-02 96 193  200  400 
#> 3 2016-09-03 143 75  200  400 
#> 4 2016-09-04 60 241  200  400 
#> 5 2016-09-05 126 225  200  400 
#> 6 2016-09-06 184 349  200  400 

Теперь мы можем использовать dplyr и tidyr (что взять на себя большую часть ответственности, которую reshape2 имеет) манипулировать данными в «ясном» способом.

library(dplyr) 
library(tidyr) 

data_clean <- data_sample %>% 
    gather(variable, value, A, B) %>% 
    mutate(limit = if_else(variable == "A", A_limit, B_limit)) %>% 
    select(Date, limit, variable, value) 

# Inspect results 
head(data_clean) 
#>   Date limit variable value 
#> 1 2016-09-01 200  A 39 
#> 2 2016-09-02 200  A 96 
#> 3 2016-09-03 200  A 143 
#> 4 2016-09-04 200  A 60 
#> 5 2016-09-05 200  A 126 
#> 6 2016-09-06 200  A 184 
Смежные вопросы