Поворот длиннее: несколько строк в столбцы в R - PullRequest
2 голосов
/ 28 февраля 2020

В настоящее время я пытаюсь понять, как развернуть мой фрейм данных (небольшой вывод ниже). В настоящее время один столбец содержит информацию о стране, код ISO, отрасли и отрасли. Мне нужно, чтобы эта информация была разбита на 4 столбца с одним соответствующим столбцом значений. Ранее я использовал функции melt и pivot_long, но не уверен, как создать 4 новых столбца, а также столбец значений.

DI_SMALL <- structure(list(V1 = structure(c(NA, NA, NA, NA, 1L, 1L, 1L, 1L
), .Label = "Energy Usage (TJ)", class = "factor"), V2 = structure(c(NA, 
NA, NA, NA, 2L, 1L, 4L, 3L), .Label = c("Coal", "Natural Gas", 
"Nuclear Electricity", "Petroleum"), class = "factor"), V3 = structure(c(5L, 
4L, 7L, 6L, 3L, 2L, 1L, 1L), .Label = c("0", "1.29327085460648e-05", 
"1.59504500372979e-05", "AFG", "Afghanistan", "Agriculture", 
"Industries"), class = "factor"), V4 = structure(c(5L, 4L, 7L, 
6L, 3L, 2L, 1L, 1L), .Label = c("0", "6.53466630114587e-06", 
"8.05944706428482e-06", "AFG", "Afghanistan", "Fishing", "Industries"
), class = "factor"), V5 = structure(c(5L, 4L, 6L, 7L, 3L, 2L, 
1L, 1L), .Label = c("0", "1.88562621206664e-05", "2.32557880912235e-05", 
"AFG", "Afghanistan", "Industries", "Mining and Quarrying"), class = "factor"), 
    V6 = structure(c(5L, 4L, 7L, 6L, 3L, 2L, 1L, 1L), .Label = c("0", 
    "2.00284547443433e-05", "2.47018365704401e-05", "AFG", "Afghanistan", 
    "Food & Beverages", "Industries"), class = "factor")), row.names = c("V1", 
"V2", "V3", "V4", "X", "X.1", "X.2", "X.3"), class = "data.frame")

В идеале выходные данные должны содержать 7 столбцов. Существующие сначала столбцы, Страна, ИСО, Промышленность и Сектор, а затем Значение. Как это:

Output <- structure(list(NA. = structure(c(1L, 1L, 1L, 1L), .Label = "Energy Usage (TJ)", class = "factor"), 
    NA..1 = structure(c(2L, 1L, 4L, 3L), .Label = c("Coal ", 
    "Natural Gas", "Nuclear Electricity", "Petroleum"), class = "factor"), 
    Country = structure(c(1L, 1L, 1L, 1L), .Label = "Afghanistan", class = "factor"), 
    ISO = structure(c(1L, 1L, 1L, 1L), .Label = "AFG", class = "factor"), 
    Industry = structure(c(1L, 1L, 1L, 1L), .Label = "Industries", class = "factor"), 
    Sector = structure(c(1L, 1L, 1L, 1L), .Label = "Agriculture", class = "factor"), 
    Value = c(1.595045004, 1.2932706, 0, 0)), class = "data.frame", row.names = c(NA, 
-4L))

Надеюсь, это имеет смысл, любые идеи будут высоко оценены!

Спасибо

Ответы [ 4 ]

2 голосов
/ 28 февраля 2020

Это не тот случай, когда pivot_long подходит, потому что у вас есть переменные, сопоставленные как со строками, так и со столбцами, и они не являются именами столбцов / строк. Вместо этого вы должны извлечь эти атрибуты из переменных, а затем создать data.frame «вручную». Вот пример, я предлагаю проверять значения переменных на каждом шаге для лучшего понимания процесса здесь:

library(dplyr)

df <- DI_SMALL %>% 
  mutate_all(as.character) 

row_attr <-  paste0(df$V1, "/", df$V2)
row_attr <- row_attr[row_attr!= "NA/NA"]

col_attr <- df[1:4, -(1:2)] %>%
  apply(MARGIN = 2, function(x) paste0(x, collapse = "/"))

values <- df[-(1:4), -(1:2)] %>%
  mutate_all(as.numeric) %>%
  as.matrix() %>%
  c()

out <- expand.grid(row_attr, col_attr)
out <- cbind(out, values)

out <- out %>% 
  tidyr::separate(col = "Var1", into = c("NA.", "NA..1"), sep = "/") %>%
  tidyr::separate(col = "Var2", 
                  into = c("Country", "ISO", "Industry", "Sector"),
                  sep = "/")

out[1:4]

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

                NA.               NA..1     Country ISO   Industry      Sector       values
1 Energy Usage (TJ)         Natural Gas Afghanistan AFG Industries Agriculture 1.595045e-05
2 Energy Usage (TJ)                Coal Afghanistan AFG Industries Agriculture 1.293271e-05
3 Energy Usage (TJ)           Petroleum Afghanistan AFG Industries Agriculture 0.000000e+00
4 Energy Usage (TJ) Nuclear Electricity Afghanistan AFG Industries Agriculture 0.000000e+00
1 голос
/ 28 февраля 2020

Используя пакет data.table, вы можете действовать следующим образом:

library(data.table)

setDT(DI_SMALL)[, V3 := as.character(V3)]
cols <- c("Country", "ISO", "Industry", "Sector")
Output <- DI_SMALL[, c(.(NA. = V1), .(NA..1 = V2), setNames(V3[is.na(V1)], cols), .(value = as.numeric(V3)))][!is.na(NA.)]

#                  NA.               NA..1     Country    ISO   Industry      Sector        value
# 1: Energy Usage (TJ)         Natural Gas Afghanistan    AFG Industries Agriculture 1.595045e-05
# 2: Energy Usage (TJ)                Coal Afghanistan    AFG Industries Agriculture 1.293271e-05
# 3: Energy Usage (TJ)           Petroleum Afghanistan    AFG Industries Agriculture 0.000000e+00
# 4: Energy Usage (TJ) Nuclear Electricity Afghanistan    AFG Industries Agriculture 0.000000e+00
1 голос
/ 28 февраля 2020

Я бы сначала поднастроил данные и работал оттуда следующим образом. Хотя я все еще не уверен, как вы получаете value в желаемом Output. Значения в выводе ниже не соответствуют тому, что вы ищете, как указано в вашем MWE. Надеюсь, это даст вам преимущество.

subV<- as.data.frame(t(DI_SMALL[grep("V", rownames(DI_SMALL)), ]))[-c(1:2), ] # transpose `t()` this subset to get your desired variable levels into columns
subX<- DI_SMALL[grep("X", rownames(DI_SMALL)), 1:3]
Output <- cbind(subX[, 1:2],  subV, subX[, 3])
colnames(Output) <- c("NA.", "NA..1", "Country", "ISO", "Industry", "Sector", "Value"); rownames(Output) <- seq(1:nrow(Output))

> Output
                NA.               NA..1     Country ISO   Industry               Sector                Value
1 Energy Usage (TJ)         Natural Gas Afghanistan AFG Industries          Agriculture 1.59504500372979e-05
2 Energy Usage (TJ)                Coal Afghanistan AFG Industries              Fishing 1.29327085460648e-05
3 Energy Usage (TJ)           Petroleum Afghanistan AFG Industries Mining and Quarrying                    0
4 Energy Usage (TJ) Nuclear Electricity Afghanistan AFG Industries     Food & Beverages                    0
0 голосов
/ 28 февраля 2020

Здесь вы можете сначала переименовать V3 в V6 с конкатенацией первых 4 строк вашего фрейма данных, затем удалить эти строки, перевернуть ваш фрейм данных в более длинный формат и, наконец, создать все четыре столбца, разделив столбец "var "создание с изменением формы, содержащим новые имена столбцов:

library(tidyr)
library(dplyr)
colNAMES <- apply(DI_SMALL[,3:6],2,function(x) paste(x[1:4],collapse="_"))
colnames(DI_SMALL)[3:6] <- colNAMES

DI_SMALL <- DI_SMALL[-c(1:4),]

DI_SMALL %>% pivot_longer(-c(V1,V2),names_to = "var",values_to = "Value") %>%
  mutate(Country = unlist(strsplit(var,"_"))[1],
         ISO = unlist(strsplit(var,"_"))[2],
         Industry = unlist(strsplit(var,"_"))[3],
         Sector = unlist(strsplit(var,"_"))[4]) %>%
  select(V1,V2,Country, ISO, Industry, Sector, Value)

# A tibble: 16 x 7
   V1                V2                  Country     ISO   Industry   Sector      Value               
   <fct>             <fct>               <chr>       <chr> <chr>      <chr>       <fct>               
 1 Energy Usage (TJ) Natural Gas         Afghanistan AFG   Industries Agriculture 1.59504500372979e-05
 2 Energy Usage (TJ) Natural Gas         Afghanistan AFG   Industries Agriculture 8.05944706428482e-06
 3 Energy Usage (TJ) Natural Gas         Afghanistan AFG   Industries Agriculture 2.32557880912235e-05
 4 Energy Usage (TJ) Natural Gas         Afghanistan AFG   Industries Agriculture 2.47018365704401e-05
 5 Energy Usage (TJ) Coal                Afghanistan AFG   Industries Agriculture 1.29327085460648e-05
 6 Energy Usage (TJ) Coal                Afghanistan AFG   Industries Agriculture 6.53466630114587e-06
 7 Energy Usage (TJ) Coal                Afghanistan AFG   Industries Agriculture 1.88562621206664e-05
 8 Energy Usage (TJ) Coal                Afghanistan AFG   Industries Agriculture 2.00284547443433e-05
 9 Energy Usage (TJ) Petroleum           Afghanistan AFG   Industries Agriculture 0                   
10 Energy Usage (TJ) Petroleum           Afghanistan AFG   Industries Agriculture 0                   
11 Energy Usage (TJ) Petroleum           Afghanistan AFG   Industries Agriculture 0                   
12 Energy Usage (TJ) Petroleum           Afghanistan AFG   Industries Agriculture 0                   
13 Energy Usage (TJ) Nuclear Electricity Afghanistan AFG   Industries Agriculture 0                   
14 Energy Usage (TJ) Nuclear Electricity Afghanistan AFG   Industries Agriculture 0                   
15 Energy Usage (TJ) Nuclear Electricity Afghanistan AFG   Industries Agriculture 0                   
16 Energy Usage (TJ) Nuclear Electricity Afghanistan AFG   Industries Agriculture 0                   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...