Разделить столбец R в CSV-файле BigCartel на длинный формат в кадре данных или в таблице данных.

У Big Cartel есть опция, которая экспортирует заказы в файл csv. Однако структура не очень хороша для анализа, который мне нужно сделать.

Вот подмножество столбцов и строк из загрузки CSV-заказа Большого картеля (есть и другие столбцы, которые не имеют значения для рассматриваемой проблемы).

Number, Buyer name,Items,Item count,Item total,Total price,Total shipping,Total tax,Total discount
1,jim,product_name:Plate|product_option_name:Red|quantity:1|price:9.99|total:9.99,1,9.99,11.98,1.99,0,0
2,bill,product_name:Plate|product_option_name:Green|quantity:1|price:9.99|total:9.99;product_name:Plate|product_option_name:Blue|quantity:1|price:9.99|total:9.99,2,19.98,22.98,3,0,0
3,jane,product_name:Plate|product_option_name:Red|quantity:1|price:6.99|total:6.99;product_name:Thingy|product_option_name:|quantity:1|price:9.99|total:9.99;product_name:Mug|product_option_name:Grey|quantity:1|price:10.99|total:10.99;product_name:Cup|product_option_name:Grey|quantity:1|price:9.99|total:9.99;product_name:Saucer|product_option_name:Grey|quantity:1|price:9.99|total:9.99;product_name:Stopper|product_option_name:|quantity:1|price:9.99|total:9.99,6,57.94,64.94,7,0,0
4,dale,product_name:Plate|product_option_name:Green|quantity:1|price:10.99|total:10.99,1,10.99,13.99,4.99,0,1.99

Столбец элементов может иметь несколько «элементов строки» с точкой с запятой (;) в качестве разделителя. Каждая «позиция» имеет пять атрибутов, разделенных вертикальной чертой (|), т. е. product_name, product_option_name, количество, цена и общая сумма (т. е. для строки). Существует столбец «Количество товаров», в котором указано количество «товаров», а также столбцы для общей цены (заказа), доставки, налогов и скидок. Для анализа мне нужны данные в следующем длинном формате, где доставка, налог и скидка также рассматриваются как «товары».

Number Buyer name line-item    product_option_name quantity price total
1      jim        Plate        Red                 1        9.99  9.99
1      jim        shipping                         1        1.99  1.99
1      jim        tax                              0        0     0
1      jim        discount                         0        0     0
2      bill       Plate        Green               1        9.99  9.99
2      bill       Plate        Blue                1        9.99  9.99
2      bill       shipping                         1        3     3
2      bill       tax                              0        0     0
2      bill       discount                         0        0     0
3      jane       Plate        Red                 1        6.99  6.99
3      jane       Thingy                           1        9.99  9.99
3      jane       Mug          Grey                1        10.99 10.99
3      jane       Cup          Grey                1        9.99  9.99
3      jane       Saucer       Grey                1        9.99  9.99
3      jane       Stopper                          1        9.99  9.99
3      jane       shipping                         1        7     7
3      jane       tax                              0        0     0
3      jane       discount                         0        0     0
4      dale       Plate        Green               1        10.99 10.99
4      dale       shipping                         1        4.99  4.99
4      dale       tax                              0        0     
4      dale       discount                         0        -1.99 -1.99

Использование tstrsplit() из r:data.table и cSplit() из r:splitstackshape кажется решением, но я не могу правильно понять синтаксис. Я также пробовал функции tidyverse/dplyr, отдельные/распространенные и т. д., но я просто не могу получить результат, который мне нужен, что бы я ни делал.

Я гуглил и просматривал все вопросы SO - есть несколько решений (этот R: разделить столбец переменных на несколько (несбалансированных) столбцов с помощью запятой), которые близки, но ни один из них не дает мне этого, поскольку большинство предполагает широкий формат, а не "длинный".


person Martyn    schedule 30.06.2017    source источник


Ответы (1)


Что-то вроде этого может дать вам то, что вы ищете.

library(dplyr)
library(tidyr)
library(stringr)

filepath <- # Path to datafile here

df <- read.csv(filepath, stringsAsFactors = FALSE)

cols <- paste0("col", 1:(max(str_count(df$Items, ";")) + 1))

df <- df %>%
      separate(col = Items, into = cols, sep = ";", fill = "right") %>%
      gather_("column", "details", cols, na.rm = TRUE) %>%
      select(-column) %>%
      separate(col = details, into = c("product_name", "product_option_name","quantity","price","total"), sep = "\\|", fill = "right") %>%
      mutate(product_name = sub("^.*\\:", "", product_name),
             product_option_name = sub("^.*\\:", "", product_option_name),
             quantity = sub("^.*\\:", "", quantity),
             price = sub("^.*\\:", "", price),
             total = sub("^.*\\:", "", total)) %>%
      gather("line", "item", c(Total.shipping, Total.discount, Total.tax, product_name)) %>%
      mutate(product_option_name = ifelse(line == "product_name" & product_option_name != "", product_option_name, NA),
             line_item = ifelse(line == "product_name", item, sub("^.*\\.","", line)),
             price = ifelse(line == "product_name", price, item),
             price = ifelse(line_item == "discount", as.numeric(price) * (-1), price),
             quantity = ifelse(line_item %in% c("shipping","discount","tax") & price == "0", 0, quantity),
             total = as.numeric(price) * as.numeric(quantity)) %>%
      distinct() %>%
      select(Number, Buyer.name, line_item, product_option_name, quantity, price, total) %>%
      arrange(Number)
person Matt Jewett    schedule 03.07.2017
comment
действительно здорово. Большое спасибо, что нашли время, чтобы посмотреть на это. Я собираюсь попробовать это на большом наборе данных, который у меня есть. - person Martyn; 04.07.2017