Как нарисовать сетевую диаграмму из столбцов фрейма данных в R?

У меня есть данные о клиентах. Я хочу нарисовать этапы клиента в виде сетевой диаграммы. Примеры данных приведены ниже.

cust_id     checkin time           stage2                     stage3              checkout time
12345   2019-01-01 07:02:50     2019-01-01 07:23:25        2019-01-01 07:23:22  2019-01-01 08:37:43
56789   2019-01-01 07:25:21     2019-01-01 07:35:29        2019-01-01 07:35:27  2019-01-01 09:36:06
43256   2019-01-01 07:27:22     2019-01-01 07:42:49        NA                   2019-01-01 09:34:55
34567   2019-01-01 07:22:15     2019-01-01 08:25:35        2019-01-01 07:26:02  2019-01-01 09:00:40
89765   2019-01-01 08:29:35     2019-01-01 08:30:58        NA                   2019-01-01 09:02:48
23456   2019-01-01 08:54:12     2019-01-01 09:18:46        2019-01-01 09:08:34  2019-01-01 09:46:38

Исходные данные выглядят так, как показано выше. Для клиента нет правила, то есть некоторые клиенты оформляют заказ после этапа 2, а некоторые клиенты должны пройти этап 3 и оформить заказ после этапа 3.

По сути, я хочу нарисовать сетевую карту этапов cusomers, как показано ниже:

checkin > stage2 > stage3 > checkout
             |
            checkout

Как это сделать в R?
Пробовал, как показано ниже, с пакетом networkD3:

library(igraph)
library(networkD3)
p <- simpleNetwork(df, height="100px", width="100px",        
                   Source = 1,                 # column number of source
                   Target = 5,                 # column number of target
                   linkDistance = 10,          # distance between node. Increase this value to have more space between nodes
                   charge = -900,                # numeric value indicating either the strength of the node repulsion (negative value) or attraction (positive value)
                   fontSize = 14,               # size of the node names
                   fontFamily = "serif",       # font og node names
                   linkColour = "#666",        # colour of edges, MUST be a common colour for the whole graph
                   nodeColour = "#69b3a2",     # colour of nodes, MUST be a common colour for the whole graph
                   opacity = 0.9,              # opacity of nodes. 0=transparent. 1=no transparency
                   zoom = T                    # Can you zoom on the figure?
)

p

Пожалуйста, помогите мне найти к нему путь.


person Navya    schedule 24.06.2020    source источник


Ответы (2)


вот одно решение с использованием _1 _...

library(tidyverse)
library(lubridate)
library(networkD3)

data <- 
  tribble(
  ~cust_id, ~checkin.time,         ~stage2,               ~stage3,               ~checkout.time,
  12345,    "2019-01-01 07:02:50", "2019-01-01 07:23:25", "2019-01-01 07:23:22", "2019-01-01 08:37:43",
  56789,    "2019-01-01 07:25:21", "2019-01-01 07:35:29", "2019-01-01 07:35:27", "2019-01-01 09:36:06",
  43256,    "2019-01-01 07:27:22", "2019-01-01 07:42:49", NA,                    "2019-01-01 09:34:55",
  34567,    "2019-01-01 07:22:15", "2019-01-01 08:25:35", "2019-01-01 07:26:02", "2019-01-01 09:00:40",
  89765,    "2019-01-01 08:29:35", "2019-01-01 08:30:58", NA,                    "2019-01-01 09:02:48",
  23456,    "2019-01-01 08:54:12", "2019-01-01 09:18:46", "2019-01-01 09:08:34", "2019-01-01 09:46:38"
  ) %>% 
  mutate(across(!cust_id, ~ymd_hms(.x, tz = "UTC")))

data %>% 
  select(-cust_id) %>% 
  mutate(across(.fns = ~if_else(is.na(.x), NA_character_, cur_column()))) %>% 
  mutate(row = row_number()) %>%
  mutate(origin = .[[1]]) %>%
  gather("column", "source", -row, -origin) %>%
  mutate(column = match(column, names(data))) %>%
  filter(!is.na(source)) %>% 
  arrange(row, column) %>%
  group_by(row) %>%
  mutate(target = lead(source)) %>%
  ungroup() %>%
  filter(!is.na(source) & !is.na(target)) %>%
  mutate(target = if_else(target == "checkout.time", paste0(target, " from ", source), target)) %>% 
  select(source, target, origin) %>%
  group_by(source, target, origin) %>%
  summarise(count = n()) %>%
  ungroup() %>%
  simpleNetwork()

введите описание изображения здесь

person CJ Yetman    schedule 24.06.2020
comment
Спасибо, что уделили этому немного времени, и когда я использовал этот код, я получаю сообщение об ошибке Error in across(!cust_id, ~ymd_hms(.x, tz = "UTC")) : could not find function "across" . Я также импортировал пакеты dplyr и tidyr. - person Navya; 26.06.2020
comment
across есть только в самой последней версии dplyr, поэтому вам придется обновиться до версии 1.0+ или преобразовать эти строки в прежний синтаксис. - person CJ Yetman; 27.06.2020
comment
@ CJ Thenman, Можно ли упорядочить узлы и включить направленные стрелки. Я видел аргументы функции simpleNetwork. В нем не было направленного истинного или какого-либо другого аргумента. - person Navya; 27.06.2020

Я нашел пакет DiagrammeR полезным. Преобразование ваших демонстрационных данных в форматы, используемые Diagrammer, было бы неудобным, поэтому я сделал это вручную.

library(DiagrammeR)

# Manually represent your data as nodes and edges
nodes <- create_node_df(n=5, label=c("Check in", "Stage 1", "Stage 2", "Stage 3", "Check out"))
edges <- create_edge_df(from = c(1, 2, 3), to = c(2, 3, 4))
lastStage <- c(4, 4, 3, 4, 3, 3)

# Create the base graph
graph <- create_graph(nodes_df=nodes, edges_df=edges) 

# Produce the customer graphs
networks <- lapply(lastStage, function(x) graph %>% add_edge(from=x, to=5) %>% render_graph())
networks[[2]]

Давая, например,

Вывод DiagrammeR

У вас есть значительный контроль над внешним видом графика. Домашняя страница DiagrammeR находится здесь.

person Limey    schedule 24.06.2020
comment
Почему вы взяли за вектор последний этап? Как определить этот вектор? - person Navya; 24.06.2020
comment
Я предполагаю, что вы хотите, чтобы каждый покупатель получил преимущество на последнем этапе, не имеющее значения NA. Значения в lastStage - это индексы соответствующего узла в nodes. Итак, Check-in имеет индекс 1, Stage 1 имеет индекс 2 и т. Д. Check-in имеет индекс 5. - person Limey; 24.06.2020
comment
Но сложно создать вручную весь фрейм данных. У меня 66k + записей с столбцами этапов. - person Navya; 24.06.2020
comment
Вам не нужно создавать его вручную. Вы можете создавать узлы и ребра из уже имеющихся данных. Я не делал этого, потому что это было бы беспорядочно и отнимало бы много времени, потому что (а) ваши данные не tidy (поскольку номер этапа отображается в именах столбцов, а не в виде значений во фрейме данных) и (б) вы не разместили свои входные данные в удобной форме . Поставьте себя на мое место и попробуйте создать data.frame, используя только информацию из вашего вопроса. dput(df) сделал бы жизнь проще. - person Limey; 24.06.2020