-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathdata_integration.Rmd
More file actions
229 lines (155 loc) · 8.69 KB
/
Copy pathdata_integration.Rmd
File metadata and controls
229 lines (155 loc) · 8.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
---
title: "Data integration"
date: "13 June 2016"
output: github_document
---
The last process before analyze and visualize the results is to integrate all the data sets.
In this phase we query, transform, group, summarize and merge information in several ways to create two datasets. The first one will hold user data and the second withdrawl data.
R package `data.table` was used again for high resource consuming tasks over a big data set with more than 7MM observations.
**Reading data**
In the first step we read the original dataset and the results obtained from running the clustering algorithm
```{r, warning=FALSE, message=FALSE}
knitr::opts_chunk$set(echo = TRUE,fig.align='center')
list.of.packages <- c("data.table", "ggplot2","ggplot2","knitr","viridis","ggthemes","knitr")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)
```
```{r, include=FALSE}
lapply(list.of.packages, library, character.only = T)
rm(list = c('list.of.packages', 'new.packages'))
```
```{r setup, include=FALSE, echo=TRUE}
# Load the data
DT <- readRDS("./data/DT.rds")
# Load the file with the clustering results
DT.r <- fread(file.path('data/results.csv'), encoding='Latin-1', na.strings=c("","NA"),stringsAsFactors = F, skip=0L)
DT.r$PER_ID_PERSONA <- gsub("\\\"\\\"", "", DT.r$PER_ID_PERSONA)
DT.r$V1 <- NULL
```
A quick plot to check how many users where assigned to each segment.
```{r, echo=TRUE, fig.height=4, fig.width=10}
# Number of users by cluster
barplot(table(DT.r$cluster), main="Number of customers by segment.", col=viridis(3), border = "white")
```
```{r}
# Load not scaled variables
DT.c <- readRDS("./data/DTc.rds")
# Add the cluster variable to scaled data frame
DT.clients <- merge(
DT.c,
DT.r[,c("PER_ID_PERSONA", "cluster"), with = FALSE],
by=c('PER_ID_PERSONA')
)
# Calculate the median for each variable by cluster
cluster_medians.df <- aggregate(DT.clients[, 2:7, with = FALSE], by = list(DT.clients$cluster), median)
write.table(cluster_medians.df, file.path('data/cluster_medians.csv'), row.names = F, col.names = TRUE, sep=",")
# Calculate the mean for each variable by cluster
setDT(DT.clients)
cluster_means.df <- DT.clients[, lapply(.SD, mean, na.rm=TRUE), by=list(DT.clients$cluster), .SDcols=c(2:7) ][order(DT.clients)]
write.table(cluster_means.df, file.path('data/cluster_means.csv'), row.names = F, col.names = TRUE, sep=",")
```
Mean and median values for each cluster:
```{r, echo=FALSE}
kable(cluster_medians.df, format = "markdown")
kable(cluster_means.df, format = "markdown")
```
A sample visualization to check the differences among clusters:
```{r, echo=FALSE, fig.height=4, fig.width=12}
p1 <- ggplot(DT.clients, aes(F1, ..density.., fill = as.factor(cluster), colour = as.factor(cluster))) +
geom_density(alpha = 0.1) +
xlim(0, 1000) + scale_fill_viridis(discrete=T) + labs(x=NULL, y=NULL, title="Median withdrawal amount into the same network by segment") + theme_tufte(base_family="Helvetica") + theme(axis.ticks=element_blank()) + theme(axis.text=element_text(size=10)) + theme(legend.title=element_text(size=8)) + theme(legend.text=element_text(size=6)) + theme(plot.title=element_text(hjust=0))
print(p1)
```
**New features**
To gain more insights form data we created some new variables to apply a RFM analysis of the users and get better knowledge from them.
```{r, fig.height=4, fig.width=12}
# RFM
# Create a new varible with the days from the previous withdrawal for each user
setorder(DT, FECHA)
DT[, DIAS_DESDE_ULT_OPER := as.numeric(difftime(time1 = FECHA, time2 = min(FECHA), units = "days")),by=.(PER_ID_PERSONA)]
# Users requests withdraw funds every 34 days, and 50% of them made it between 10 and 55 days
summary(DT$DIAS_DESDE_ULT_OPER)
# Frequency chart of days since last withdrawal
barplot(table(DT[DIAS_DESDE_ULT_OPER > 0,]$DIAS_DESDE_ULT_OPER), main="# number of withdrawals by days from last withdrawal" , col=viridis(1), border = "white")
```
**Visualizing recency, frequency and average withdrawal amount**
```{r}
# New variables with recency, frequency and monetary value for each user
DT.rfm <- DT[, list( RECENCIA = mean(DIAS_DESDE_ULT_OPER, na.rm = T),
FRECUENCIA = unique(.N),
VALOR_MEDIO = median(IMPOPER, na.rm = T)
)
,by=.(PER_ID_PERSONA)]
# Merge the new variables with our users data frame
DT.clients <- merge(
DT.clients,
DT.rfm,
by=c('PER_ID_PERSONA')
)
p3 <- ggplot(DT.clients[,mean(RECENCIA, na.rm = T),by=.(cluster)], aes(x= as.factor(cluster), fill=as.factor(cluster))) + geom_bar() + stat_summary_bin(aes(y = V1), fun.y = "mean", geom = "bar") + scale_fill_viridis(discrete=T) + labs(x=NULL, y=NULL, title="Recency") + theme_tufte(base_family="Helvetica") + theme(axis.ticks=element_blank()) + theme(axis.text=element_text(size=10)) + theme(legend.title=element_text(size=8)) + theme(legend.text=element_text(size=6)) + theme(plot.title=element_text(hjust=0))
p4 <- ggplot(DT.clients[,mean(FRECUENCIA, na.rm = T),by=.(cluster)], aes(x= as.factor(cluster), fill=as.factor(cluster))) + geom_bar() + stat_summary_bin(aes(y = V1), fun.y = "mean", geom = "bar") + scale_fill_viridis(discrete=T) + labs(x=NULL, y=NULL, title="Frequency") + theme_tufte(base_family="Helvetica") + theme(axis.ticks=element_blank()) + theme(axis.text=element_text(size=10)) + theme(legend.title=element_text(size=8)) + theme(legend.text=element_text(size=6)) + theme(plot.title=element_text(hjust=0))
p5 <- ggplot(DT.clients[,mean(VALOR_MEDIO, na.rm = T),by=.(cluster)], aes(x= as.factor(cluster), fill=as.factor(cluster))) + geom_bar() + stat_summary_bin(aes(y = V1), fun.y = "mean", geom = "bar") + scale_fill_viridis(discrete=T) + labs(x=NULL, y=NULL, title="Average withdrawal amount") + theme_tufte(base_family="Helvetica") + theme(axis.ticks=element_blank()) + theme(axis.text=element_text(size=10)) + theme(legend.title=element_text(size=8)) + theme(legend.text=element_text(size=6)) + theme(plot.title=element_text(hjust=0))
```
The next three plot let us easily inspect the different behaviour among user in each segment.
```{r, echo=FALSE, fig.height=4, fig.width=8}
print(p3)
print(p4)
print(p5)
```
**New features**
```{r}
# Calculating user age and account duration
DT.clients <- merge(
DT.clients,
DT[!duplicated(DT$PER_ID_PERSONA), list(
PER_ANTIGUEDAD = round(julian(as.Date(Sys.Date()), as.Date(PER_FECHA_ALTA))/365.25, 0),
PER_EDAD = round(julian(as.Date(Sys.Date()), as.Date(PER_FECHA_NAC))/365.25,0)
), by = .(PER_ID_PERSONA)],
by=c('PER_ID_PERSONA')
)
p6 <- ggplot(DT.clients[,mean(PER_EDAD, na.rm = T),by=.(cluster)], aes(x= as.factor(cluster), y=V1, fill=as.factor(cluster))) + geom_bar(stat = "identity") + scale_fill_viridis(discrete=T) + labs(x=NULL, y=NULL, title="Average user age by segment") + theme_tufte(base_family="Helvetica") + theme(axis.ticks=element_blank()) + theme(axis.text=element_text(size=10)) + theme(legend.title=element_text(size=8)) + theme(legend.text=element_text(size=6)) + theme(plot.title=element_text(hjust=0))
```
```{r, echo=FALSE, fig.height=4, fig.width=8}
print(p6)
```
```{r}
# Adding user information
DT.clients <- merge(
DT.clients,
DT[!duplicated(DT$PER_ID_PERSONA),c("PER_ID_PERSONA", "PER_ID_SEXO", "PER_EST_CIVIL", "PER_COD_PAIS_NAC"), with = FALSE],
by=c('PER_ID_PERSONA')
)
```
```{r}
# Derive new variables from the original ones for better undestanding of each cluster
client_means.df <- as.data.frame(DT.clients[, lapply(.SD, mean, na.rm=TRUE), by=list(DT.clients$cluster), .SDcols=c(9:11,13) ][order(DT.clients)])
# Export the result for data visualization in Tableu
write.table(client_means.df, file.path('data/tableau_rfm.csv'), row.names = F, col.names = TRUE, sep=",")
# Export client data for visualization in Tableu
write.table(DT.clients, file.path('data/tableau_clients.csv'), row.names = F, col.names = TRUE, sep=",")
```
**Mean recency, frequency, amount and user age by cluster**
```{r, echo=FALSE}
kable(round(client_means.df, 0), format = "markdown")
```
**Users dataset**
The final users dataset with relevant variables:
```{r, echo=FALSE}
kable(head(DT.clients, 4), format = "markdown")
```
## Withdrawal data
```{r}
# Add user cluster assignment to each operation
DT.transactons <- merge(
DT,
DT.r[,c("PER_ID_PERSONA", "cluster"), with = FALSE],
by=c('PER_ID_PERSONA')
)
barplot(table(DT.transactons$cluster), main= "Number of successfull withdrowals requests by segment ",col=viridis(4), border = "white")
# Export withdrawals data for visualization in Tableu
write.table(DT.transactons, file.path('data/tableau_operaciones.csv'), row.names = F, col.names = TRUE, sep=",")
```
The final withdrawal dataset:
```{r, echo=FALSE}
kable(head(DT.transactons, 2), format = "markdown")
```