Управление вложенными данными - PullRequest
0 голосов
/ 12 февраля 2019

Я новичок в r, и у меня возникли проблемы с манипулированием данными так, как они мне нужны для анализа.Я был бы признателен, если кто-нибудь мог бы помочь.

мои данные выглядят примерно так:

df<- data.frame("Reporter" = c("USA", "USA", "USA", "USA", "USA","USA"),
"Partner" = c( "EU", "EU","EU","EU", "EU","EU"), 
"Product cat." = c("1", "11", "111", "122", "12", "2"), 
"Year" = c(1970, 1970, 1970, 1970, 1970, 1970), 
"trade value" = c( 100, 50, 25, 5, 40, 220), stringsAsFactors = FALSE)

У меня есть несколько наблюдений за год по стране с данными о торговле о торговле.Векторное произведение.cat указывает, какой товар экспортируется. Чем больше цифр, тем товар.кошка имеет, чем больше дезагрегирована торговая информация .Например товар кат.111 (например, яблоко) и 112 (например, бананы) - это категории субпродуктов категории 11 (например, фрукты).Товарная категория 11 является подкатегорией продуктов питания (товар кат.1).

Чтобы провести анализ, мне нужно, чтобы все значения были представлены на максимально дезагрегированном уровне - т.е. мне нужно, чтобы все данные имели максимально возможное количество цифр.

Моя проблема в том, что по некоторым наблюдениям за год у меня есть данные, представленные только на более высоком уровне агрегирования.Например, рассмотрим следующий список продуктов cat.в качестве сравнения для примера.

ls.prod.cat<- data.frame(
  "Product cat." = c("1", "11", "111", "122", "12","121","122","2","21","22","211"), 
 stringsAsFactors = FALSE)

В этом примере у меня есть данные, представленные на уровне 2 цифр (12), которые могут быть представлены на уровне 3 цифр (121, 122).Я хотел бы найти способ индивидуализировать все данные, представленные только на более высоком уровне агрегации (например, например, 12), и изменить их продукт cat.добавив "м" в конце.Отсюда после манипулирования продуктом кат.12 должно стать 12m .

Аналогично для более высоких уровней агрегации.Например, когда данные сообщаются только по первой цифре продукта кат.цифра Я хотел бы иметь данные, которые добавляют два "мм" в конце продукта кат.чтобы отразить, что данные представляются только на первом уровне агрегирования.Например, в моем df это означает, что данные, в которых есть продукт cat.2 должен стать продуктом кат. 2 мм

---- ОБНОВЛЕНИЕ ---

В общем, я ищу способ автоматической индивидуализации строк, где данные исключительно сообщается на более высоком уровне агрегации и в этих строках изменяется продукт кат.имя, добавив соответствующие номера м.Только для данных, для которых у меня есть только данные на более высоком уровне агрегирования, следует включать «m».Например, в этом примере я не хочу иметь 1 мм, поскольку у меня есть данные с более низким уровнем агрегирования (11,12).Точно так же я не хочу иметь 11 млн., Потому что у меня есть данные на более низких уровнях агрегации (111 112).То, что я хотел бы иметь, это 12м.поскольку данные по 121 и 122 должны существовать (ср. ls.prod.cat), но данные представляются только на более высоком уровне агрегирования (12).

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

---- ОБНОВЛЕНИЕ 2 ---

рассмотрим более сложный набор данных

df3 <- <- data.frame(
"Reporter" = c("USA", "USA", "USA", "USA", "USA", "USA","USA", "USA", 
"USA","USA","EU", "EU","EU","EU","EU", "EU","EU","EU","EU", "EU", 
"USA", "USA", "USA", "USA", "USA", "USA","USA", "USA", "USA","USA"),
"Partner" = c( "EU", "EU","EU","EU", "EU","EU","EU", 
"EU","EU","EU","USA", "USA", "USA","USA","USA", "USA", 
"USA","USA","USA", "USA", "EU", "EU","EU","EU", "EU","EU","EU", 
"EU","EU","EU"), 
"Product cat." = c("1", "11", "111", "112", "12","2", "21","211", "22", 
"3", "1", "11", "111", "112", "2", "21", "211", "212", "22", "221", 
"1", "11", "111", "112", "12","2", "21","211", "22", "3"), 
"Year" = c(1970, 1970, 1970, 1970, 1970,1970, 1970, 1970, 1970, 1970, 
1970, 1970, 1970, 1970, 1970, 1970, 1970, 1970, 1970, 1970, 1980, 1980, 
1980, 1980,  1980, 1980, 1980, 1980, 1980, 1980), 
"Val" = c( 100, 50, 25, 5, 40, 200, 170, 170, 30, 220, 190, 190, 120, 
30, 300, 200, 150, 50, 100, 100, 150, 50, 25,25, 100, 300, 120, 100, 
160, 200), 
stringsAsFactors = FALSE)

, когда я запускаю функцию fillLevel для своего кода

fillLevel <- function(x, width = 3, fill = "m"){ sp <- split(x, substr(x, 1, 1)) sp <- lapply(seq_along(sp), function(i){ n <- nchar(sp[[i]]) if(all(n < 3)){ j <- which(n == max(n)) sp[[i]][j] <- gsub(" ", "m", formatC(sp[[i]][j], width = -3)) } sp[[i]] }) unname(unlist(sp))}

Происходит какая-то странная вещь m.df3 <- df3 %>% mutate(m.prodcat = fillLevel(Product cat.)) В частности, категории m.prodcat не соответствуют product cat..Например, экспорт США в ЕС отличается от товара кат.2 до m.prodcat 1 , от продукта кат.С 21 по м.продкат 11 и тд.со многими другими несоответствиями.

Кто-нибудь знает, в чем может быть причина?Большое спасибо за вашу помощь

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Вот вариант с str_pad

library(dplyr)
library(stringr)
df %>% 
  mutate(Product.cat. = str_pad(Product.cat., width = 3, pad = "m", side = "right"))
#  Reporter Partner Product.cat. Year trade.value
#1      USA      EU          1mm 1970         100
#2      USA      EU          11m 1970          50
#3      USA      EU          111 1970          25
#4      USA      EU          122 1970           5
#5      USA      EU          12m 1970          40
#6      USA      EU          2mm 1970         220
0 голосов
/ 13 февраля 2019

Другой способ - использовать stri_pad_rigth() из stringi:

library(stringi)
library(dplyr)

mutate(df, Product.cat. = stri_pad_right(Product.cat., 3, 'm'))

  Reporter Partner Product.cat. Year trade.value
1      USA      EU          1mm 1970         100
2      USA      EU          11m 1970          50
3      USA      EU          111 1970          25
4      USA      EU          122 1970           5
5      USA      EU          12m 1970          40
6      USA      EU          2mm 1970         220

readr::str_pad(), под капотом используются функции stringi::stri_pad_*():

> str_pad
function (string, width, side = c("left", "right", "both"), pad = " ") 
{
    side <- match.arg(side)
    switch(side, left = stri_pad_left(string, width, pad = pad), 
        right = stri_pad_right(string, width, pad = pad), both = stri_pad_both(string, 
            width, pad = pad))
}
<bytecode: 0x566a028>
<environment: namespace:stringr>
0 голосов
/ 12 февраля 2019

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

df2 <- data.frame("Reporter" = c("USA", "USA", "USA", "USA", "USA","USA", "USA", "USA"),
                 "Partner" = c( "EU", "EU","EU","EU", "EU","EU","EU", "EU"), 
                 "Product cat." = c("1", "11", "111", "122", "12", "2", "3", "31"), 
                 "Year" = c(1970, 1970, 1970, 1970, 1970, 1970, 1970, 1970), 
                 "trade value" = c( 100, 50, 25, 5, 40, 220, 120, 20), stringsAsFactors = FALSE)


fillLevel <- function(x, width = 3, fill = "m"){
  sp <- split(x, substr(x, 1, 1))
  sp <- lapply(seq_along(sp), function(i){
    n <- nchar(sp[[i]])
    if(all(n < 3)){
      j <- which(n == max(n))
      sp[[i]][j] <- gsub(" ", "m", formatC(sp[[i]][j], width = -3))
    }
    sp[[i]]
  })
  unname(unlist(sp))
}

fillLevel(df$Product.cat.)
#[1] "1"   "11"  "111" "122" "12"  "2mm"

fillLevel(df2$Product.cat.)
#[1] "1"   "11"  "111" "122" "12"  "2mm" "3"   "31m"

Теперь присвойте результат функции как угодно, будь то новый столбец или исходный.

...