如何修复销售漏斗的ggplot2代码?

时间:2017-03-01 20:56:51

标签: r ggplot2

我尝试运行提到here的代码:

library(dplyr)
library(ggplot2)
library(reshape2)

# creating a data samples
# content
df.content <- data.frame(content = c('main', 'ad landing',
'product 1', 'product 2', 'product 3', 'product 4',
'shopping cart',
'thank you page'),
step = c('awareness', 'awareness',
'interest', 'interest', 'interest', 'interest',
'desire',
'action'),
number = c(150000, 80000,
80000, 40000, 35000, 25000,
130000,
120000))
# customers
df.customers <- data.frame(content = c('new', 'engaged', 'loyal'),
step = c('new', 'engaged', 'loyal'),
number = c(25000, 40000, 55000))
# combining two data sets
df.all <- rbind(df.content, df.customers)

# calculating dummies, max and min values of X for plotting
df.all <- df.all %>%
group_by(step) %>%
mutate(totnum = sum(number)) %>%
ungroup() %>%
mutate(dum = (max(totnum) - totnum)/2,
maxx = totnum + dum,
minx = dum)

# data frame for plotting funnel lines
df.lines <- df.all %>%
select(step, maxx, minx) %>%
group_by(step) %>%
unique()

# data frame with dummies
df.dum <- df.all %>%
select(step, dum) %>%
unique() %>%
mutate(content = 'dummy',
number = dum) %>%
select(content, step, number)

# data frame with rates
conv <- df.all$totnum[df.all$step == 'action']

df.rates <- df.all %>%
select(step, totnum) %>%
group_by(step) %>%
unique() %>%
ungroup() %>%
mutate(prevnum = lag(totnum),
rate = ifelse(step == 'new' | step == 'engaged' | step == 'loyal',
round(totnum / conv, 3),
round(totnum / prevnum, 3))) %>%
select(step, rate)
df.rates <- na.omit(df.rates)

# creting final data frame
df.all <- df.all %>%
select(content, step, number)

df.all <- rbind(df.all, df.dum)

df.all <- df.all %>%
group_by(step) %>%
arrange(desc(content)) %>%
ungroup()

# calculating position of labels
df.all <- df.all %>%
group_by(step) %>%
mutate(pos = cumsum(number) - 0.5*number)

# defining order of steps
df.all$step <- factor(df.all$step, levels = c('loyal', 'engaged', 'new', 'action', 'desire', 'interest', 'awareness'))
list <- c(unique(as.character(df.all$content)))
df.all$content <- factor(df.all$content, levels = c('dummy', c(list)))

# creating custom palette with 'white' color for dummies
cols <- c("#ffffff", "#fec44f", "#fc9272", "#a1d99b", "#fee0d2", "#2ca25f",
"#8856a7", "#43a2ca", "#fdbb84", "#e34a33",
"#a6bddb", "#dd1c77", "#ffeda0", "#756bb1")

# plotting chart
ggplot() +
theme_minimal() +
coord_flip() +
scale_fill_manual(values=cols) +
geom_bar(data=df.all, aes(x=step, y=number, fill=content), stat="identity", width=1) +
geom_text(data=df.all[df.all$content!='dummy', ],
aes(x=step, y=pos, label=paste0(content, '-', number/1000, 'K')),
size=4, color='white', fontface="bold") +
geom_ribbon(data=df.lines, aes(x=step, ymax=max(maxx), ymin=maxx, group=1), fill='white') +
geom_line(data=df.lines, aes(x=step, y=maxx, group=1), color='darkred', size=4) +
geom_ribbon(data=df.lines, aes(x=step, ymax=minx, ymin=min(minx), group=1), fill='white') +
geom_line(data=df.lines, aes(x=step, y=minx, group=1), color='darkred', size=4) +
geom_text(data=df.rates, aes(x=step, y=(df.lines$minx[-1]), label=paste0(rate*100, '%')), hjust=1.2,
color='darkblue', fontface="bold") +
theme(legend.position='none', axis.ticks=element_blank(), axis.text.x=element_blank(),
axis.title.x=element_blank())

因为我遇到了重复因素错误:

Warning message:
In `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels) else paste0(labels,  :
  duplicated levels in factors are deprecated

结果这个丑陋的情节 enter image description here

我改变了这段代码:

df.all$content <- factor(df.all$content, levels = c('dummy', c(list)))

成:

df.all$content <- factor(df.all$content, levels = c(list)))

结果我得到了这个情节:enter image description here

根据博客作者的说法,这应该是结果:

enter image description here

我想我不必解释我的阴谋不是他们应该的样子。我还没弄清楚导致问题的原因。有谁知道这里发生了什么以及如何解决它?

2 个答案:

答案 0 :(得分:1)

问题是每个栏中组的顺序是..well,不按顺序。

可能会因# Send an HTML email with an embedded image and a plain text message for # email clients that don't want to display the HTML. import datetime import time import smtplib import urllib2 import RPi.GPIO as gpio gpio.setmode(gpio.BCM) gpio.setup(17, gpio.IN, pull_up_down = gpio.PUD_DOWN) from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText from email.MIMEImage import MIMEImage dtnow = datetime.datetime.now().strftime("%m-%d-%Y %H:%M:%S") print 'SMTP Doorbell Application loaded @ ' + dtnow smtpServer = 'smtp.server.com' smtpPort = '587' smtpUser = 'smtuser@email.com' smtpPass = 'P@ssword1' strFrom = 'fromname@email.com' strTo = 'toname@email.com' # Create the root message and fill in the from, to, and subject headers msgRoot = MIMEMultipart('related') msgRoot['Subject'] = 'RPI - Doorbell Alert' msgRoot['From'] = strFrom msgRoot['To'] = strTo msgRoot.preamble = 'This is a multi-part message in MIME format.' header = 'From: ' + strFrom + '\n' + 'To: ' + strTo + '\n' + 'Subject: RPI - Doorbell Alert' while True: input_value = gpio.input(17) if input_value == False: print("\033c") dtnow = datetime.datetime.now().strftime("%m-%d-%Y %H:%M:%S") print 'Doorbell has been pressed @ ' + dtnow # Encapsulate the plain and HTML versions of the message body in an # 'alternative' part, so message agents can decide which they want to display. msgAlternative = MIMEMultipart('alternative') msgRoot.attach(msgAlternative) dtnow = datetime.datetime.now().strftime("%m-%d-%Y %H:%M:%S") msgText = MIMEText('Doorbell Rang @ ' + dtnow) msgAlternative.attach(msgText) # We reference the image in the IMG SRC attribute by the ID we give it below msgText = MIMEText('Doorbell Rang @ ' + dtnow + ' <br><img src="cid:image1">', 'html') msgAlternative.attach(msgText) # Get ReoLink Image request = urllib2.Request( r'http://192.168.0.11/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=wuuPhkmUCeI9WG7C&user=admin&password=12345', headers={'User-Agent':'Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 firefox/2.0.0.11'}) page = urllib2.urlopen(request) with open('doorbell.png','wb') as f: f.write(page.read()) # This example assumes the image is in the current directory fp = open('doorbell.png', 'rb') msgImage = MIMEImage(fp.read()) fp.close() # Define the image's ID as referenced above msgImage.add_header('Content-ID', '<image1>') msgRoot.attach(msgImage) # Send the email (this example assumes SMTP authentication is required) smtp = smtplib.SMTP(smtpServer, smtpPort) smtp.ehlo() smtp.starttls() smtp.ehlo() smtp.login(smtpUser,smtpPass) smtp.sendmail(strFrom, strTo.split(','), msgRoot.as_string()) time.sleep(15) smtp.quit() print 'SMS sent successful!' print header + '\n' + 'Message: Doorbell Rang @ ' + dtnow while input_value == False: input_value = gpio.input(17) 排序因素而发生变化,无论如何都要解决问题:

ggplot

有效位是:

ggplot() +
  theme_minimal() +
  coord_flip() +
  scale_fill_manual(values=cols) +
  geom_bar(data=df.all, aes(x=step, y=number, fill=content), position = position_stack(reverse = T), width=1, stat = 'identity') +
  geom_text(data=df.all[df.all$content!='dummy', ],
            aes(x=step, y=pos, label=paste0(content, '-', number/1000, 'K')),
            size=4, color='white', fontface="bold") +
  geom_ribbon(data=df.lines, aes(x=step, ymax=max(maxx), ymin=maxx, group=1), fill='white') +
  geom_line(data=df.lines, aes(x=step, y=maxx, group=1), color='darkred', size=4) +
  geom_ribbon(data=df.lines, aes(x=step, ymax=minx, ymin=min(minx), group=1), fill='white') +
  geom_line(data=df.lines, aes(x=step, y=minx, group=1), color='darkred', size=4) +
  geom_text(data=df.rates, aes(x=step, y=(df.lines$minx[-1]), label=paste0(rate*100, '%')), hjust=1.2,
            color='darkblue', fontface="bold") +
  theme(legend.position='none', axis.ticks=element_blank(), axis.text.x=element_blank(),
        axis.title.x=element_blank())

请注意,这应该更新为使用geom_bar(data=df.all, aes(x=step, y=number, fill=content), position = position_stack(reverse = T), width=1, stat = 'identity')

geom_col

正如@Uwe Block所说,这仍然是一个丑陋而难以阅读的内容。一些更好的东西是Sankey图。

结果:

enter image description here

答案 1 :(得分:1)

问题是由于包中的一些更新。工作代码如下:

library(dplyr)
library(ggplot2)
library(reshape2)

# creating a data samples
# content
df.content <- data.frame(content = c('main', 'ad landing',
                                  'product 1', 'product 2', 'product 3', 'product 4',
                                  'shopping cart',
                                  'thank you page'),
                         step = c('awareness', 'awareness',
                                   'interest', 'interest', 'interest', 'interest',
                                   'desire',
                                   'action'),
                         number = c(150000, 80000,
                                    80000, 40000, 35000, 25000,
                                    130000,
                                    120000))
# customers
df.customers <- data.frame(content = c('new', 'engaged', 'loyal'),
                           step = c('new', 'engaged', 'loyal'),
                           number = c(25000, 40000, 55000))
# combining two data sets
df.all <- rbind(df.content, df.customers)

# calculating dummies, max and min values of X for plotting
df.all <- df.all %>%
    group_by(step) %>%
    mutate(totnum = sum(number)) %>%
    ungroup() %>%
    mutate(dum = (max(totnum) - totnum)/2,
           maxx = totnum + dum,
           minx = dum)

# data frame for plotting funnel lines
df.lines <- df.all %>%
    distinct(step, maxx, minx)

# data frame with dummies
df.dum <- df.all %>%
    distinct(step, dum) %>%
    mutate(content = 'dummy',
           number = dum) %>%
    select(content, step, number)

# data frame with rates
conv <- df.all$totnum[df.all$step == 'action']

df.rates <- df.all %>%
    distinct(step, totnum) %>%
    mutate(prevnum = lag(totnum),
           rate = ifelse(step == 'new' | step == 'engaged' | step == 'loyal',
                         round(totnum / conv, 3),
                         round(totnum / prevnum, 3))) %>%
    select(step, rate)
df.rates <- na.omit(df.rates)

# creting final data frame
df.all <- df.all %>%
    select(content, step, number)

df.all <- rbind(df.all, df.dum)

# defining order of steps
df.all$step <- factor(df.all$step, levels = c('loyal', 'engaged', 'new', 'action', 'desire', 'interest', 'awareness'))
df.all <- df.all %>%
        arrange(desc(step))
list1 <- df.all %>% distinct(content) %>%
        filter(content != 'dummy')
df.all$content <- factor(df.all$content, levels = c(as.character(list1$content), 'dummy'))

# calculating position of labels
df.all <- df.all %>%
        arrange(step, desc(content)) %>%
        group_by(step) %>%
        mutate(pos = cumsum(number) - 0.5*number) %>%
        ungroup()

# creating custom palette with 'white' color for dummies
cols <- c("#fec44f", "#fc9272", "#a1d99b", "#fee0d2",
          "#2ca25f", "#8856a7", "#43a2ca", "#fdbb84",
          "#e34a33", "#a6bddb", "#dd1c77", "#ffffff")

# plotting chart
ggplot() +
    theme_minimal() +
    coord_flip() +
    scale_fill_manual(values=cols) +
    geom_bar(data=df.all, aes(x=step, y=number, fill=content), stat="identity", width=1) +
    geom_text(data=df.all[df.all$content!='dummy', ],
              aes(x=step, y=pos, label=paste0(content, '-', number/1000, 'K')),
              size=4, color='white', fontface="bold") +
    geom_ribbon(data=df.lines, aes(x=step, ymax=max(maxx), ymin=maxx, group=1), fill='white') +
    geom_line(data=df.lines, aes(x=step, y=maxx, group=1), color='darkred', size=4) +
    geom_ribbon(data=df.lines, aes(x=step, ymax=minx, ymin=min(minx), group=1), fill='white') +
    geom_line(data=df.lines, aes(x=step, y=minx, group=1), color='darkred', size=4) +
    geom_text(data=df.rates, aes(x=step, y=(df.lines$minx[-1]), label=paste0(rate*100, '%')), hjust=1.2,
              color='darkblue', fontface="bold") +
    theme(legend.position='none', axis.ticks=element_blank(), axis.text.x=element_blank(), 
          axis.title.x=element_blank())