Как разбить столбцы с тремя именами атрибутов данных на несколько столбцов, а затем разбить на разные уровни агрегации? - PullRequest
0 голосов
/ 19 октября 2018

У меня есть большой фрейм данных, который принимает форму ниже, где каждый столбец обозначает год, товар и единицу.Каждое наблюдение соответствует шахте, и каждое значение является произведенным количеством.

library(tibble)
rdf <- tribble(
  ~`1997_Silver_oz`, ~`1998_Diamonds_ct`, ~`1999_Coal_lbs`, ~`1999_Copper_tonnes`,
    150000, 20000, NA_integer_, NA_integer_,
    NA_integer_, 50000, NA_integer_, 1,
    NA_integer_, NA_integer_, NA_integer_, NA_integer_,
    40000, 205000, NA_integer_, NA_integer_
)

Я хочу свернуть эти данные до двух уровней агрегации, чтобы увидеть, где существует ненулевое производство для каждого года и товара / года.

Что такое промежуточный этап Iнужно разделить мои существующие столбцы на несколько, как показано ниже?

rdf_gathered <- tribble(
  ~year, ~commodity, ~unit, ~amount,
   1997, 'Silver', 'oz', 150000,
   1997, 'Silver', 'oz', NA_integer_,
   1997, 'Silver', 'oz', NA_integer_,
   1997, 'Silver', 'oz', 40000,
   1998, 'Diamonds', 'ct', 20000,
   1998, 'Diamonds', 'ct', 50000,
   1998, 'Diamonds', 'ct', NA_integer_,
   1998, 'Diamonds', 'ct', 205000,
   1999, 'Coal', 'lbs', NA_integer_,
   1999, 'Coal', 'lbs', NA_integer_,
   1999, 'Coal', 'lbs', NA_integer_,
   1999, 'Coal', 'lbs', NA_integer_,
   1999, 'Copper', 'tonnes', NA_integer_,
   1999, 'Copper', 'tonnes', 1,
   1999, 'Copper', 'tonnes', NA_integer_,
   1999, 'Copper', 'tonnes', NA_integer_
)

И после этого шага, какой шаг мне нужно предпринять, чтобы свернуть этот фрейм данных в один, который измеряет ненулевое производство, как показано ниже?[NA -> 0, еще 1]

# Collapse
rdf_collapsed_v1 <- tribble(
  ~`1997_Silver`, ~`1998_Diamonds`, ~`1999_Coal`, ~`1999_Copper`,
    1, 1, 0, 1
) 

rdf_collapsed_v2 <- tribble(
  ~`1997`, ~`1998`, ~`1999`,
  1, 1, 1
) 

Я использую / в основном предпочитаю функции обратного хода, но также заинтересован в любом изящном базовом решении.

Ответы [ 2 ]

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

Вот несколько простых операций dplyr.

Единственный сложный бит - это когда я использую summarise и any для создания логического теста по группе, а затем умножаю *1 на преобразование этого логического результата в двоичный (0 или 1).any отлично подходит для групп тестирования!

library(tidyverse)
#Data
rdf <- tribble(
  ~`1997_Silver_oz`, ~`1998_Diamonds_ct`, ~`1999_Coal_lbs`, ~`1999_Copper_tonnes`,
    150000, 20000, NA_integer_, NA_integer_,
    NA_integer_, 50000, NA_integer_, 1,
    NA_integer_, NA_integer_, NA_integer_, NA_integer_,
    40000, 205000, NA_integer_, NA_integer_
)  

# Create Tidy Data  
rdf <- rdf %>% 
    gather(key, value) %>% 
    separate(key, into= c("year", "commodity", "unit"), sep="_") %>% 
    mutate(value = replace_na(value, 0))

# A tibble: 16 x 4
   year  commodity unit    value
   <chr> <chr>     <chr>   <dbl>
 1 1997  Silver    oz     150000
 2 1997  Silver    oz          0
 3 1997  Silver    oz          0
 4 1997  Silver    oz      40000
 5 1998  Diamonds  ct      20000
 6 1998  Diamonds  ct      50000
 7 1998  Diamonds  ct          0
 8 1998  Diamonds  ct     205000
 9 1999  Coal      lbs         0
10 1999  Coal      lbs         0
11 1999  Coal      lbs         0
12 1999  Coal      lbs         0
13 1999  Copper    tonnes      0
14 1999  Copper    tonnes      1
15 1999  Copper    tonnes      0
16 1999  Copper    tonnes      0

# First Operation
rdf %>% 
  group_by(year,commodity) %>% 
  summarise(non.zero = any(value>0)*1 ) %>% 
  unite("year_commodity", c("year", "commodity"), sep = "_", remove = T) %>% 
  spread(year_commodity, non.zero)

#> # A tibble: 1 x 4
#>   `1997_Silver` `1998_Diamonds` `1999_Coal` `1999_Copper`
#>           <dbl>           <dbl>       <dbl>         <dbl>
#> 1             1               1           0             1

#Second Operation
rdf %>% 
  group_by(year) %>% 
  summarise(non.zero = any(value>0)*1 ) %>% 
  spread(year, non.zero)

#> # A tibble: 1 x 3
#>   `1997` `1998` `1999`
#>    <dbl>  <dbl>  <dbl>
#> 1      1      1      1

Создано в 2018-10-19 пакетом Представить (v0.2.1)

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

Вы можете использовать gather и separate для первого задания

library(tidyr)
rdf_gathered <- gather(rdf, key, amount) %>% 
  separate(col = key, into = c("year", "commodity", "unit"))
rdf_gathered
# A tibble: 16 x 4
#   year  commodity unit   amount
#   <chr> <chr>     <chr>   <dbl>
# 1 1997  Silver    oz     150000
# 2 1997  Silver    oz         NA
# 3 1997  Silver    oz         NA
# 4 1997  Silver    oz      40000
# ...

А вот подход base R для второго задания

rdf_collapsed_v1 <- sapply(rdf, function(x) as.integer(!is.na(x)))
#     1997_Silver_oz 1998_Diamonds_ct 1999_Coal_lbs 1999_Copper_tonnes
#[1,]              1                1             0                  0
#[2,]              0                1             0                  1
#[3,]              0                0             0                  0
#[4,]              1                1             0                  0

Это дает matrix, поэтому при необходимости оберните его в as.data.frame.


Для третьего вы можете использовать rdf_gathered и dplyr глаголы.

library(dplyr)
rdf_gathered %>% 
  mutate(amount = as.integer(!is.na(amount))) %>% 
  group_by(year) %>% 
  summarise(amount = sum(amount))
# A tibble: 3 x 2
#  year  amount
#  <chr>  <int>
#1 1997       2
#2 1998       3
#3 1999       1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...