Press "Enter" to skip to content

R人力分析工具包:讲述您的员工人数故事

使用R解决人员分析中的常见挑战

来自Tolga Ulkan在Unsplash上的照片

在人员分析工作中,您经常被要求讲述公司人数和公司如何发展到今天的故事。我经常看到这以瀑布图的形式展示,这很好,但是在向非技术人员分享年度变化时会变得混乱。

为了满足这个需求,我创建了迭代绘图,突出了每一年的一些额外上下文。然后,可以将这些绘图添加到幻灯片中,逐年进行演示,或者将它们一起制作成gif。让我们一起制作它!

使用面积图的gif讲述的时间内的人数。图片由作者提供。

挑战:讲述我们的人数如何年度变化到现在。

步骤:1. 加载必要的包和数据 2. 计算每月人数 3. 为每一年添加相关上下文 4. 创建绘图 5. 设置自动创建每年的绘图 6. 调整主题和绘图格式

1. 加载必要的包和数据

为了完成这个挑战,我们需要以下包:- tidyverse – hrbrthemes(用于使我们的绘图更美观)

为了创建我们的可视化效果,我们需要一个包含唯一标识符(例如员工ID)、入职日期和离职日期的文件。在这个示例中,我将使用模拟数据(在底部我已经包含了用于制作模拟数据的代码,如果您想一步一步跟随)。

# 加载包library(tidyverse)library(hrbrthemes)# 加载数据employee_data <- mock_data # 或者您可以使用类似 employee_data <- read.csv("input.csv")

顺便说一句,我通常将原始读入的数据分配给一个变量,然后创建一个新的变量用于未来的操作。这并不总是必要的,但是当使用大型数据集时,可以加快速度,这样每次需要更改代码时就不必重新加载数据。

原始输入数据的一瞥。图片由作者提供。

为了使计算正确工作,我们需要确保R知道入职日期和离职日期实际上是日期。一般来说,在R中处理日期可能会很麻烦,但是为了完成这个挑战,我们需要将日期列格式化为日期,并且没有NA值。

df <- employee_data %>%  mutate(Hire.Date = as.Date(Hire.Date, format = "%m/%d/%Y"),         Termination.Date = as.Date(Termination.Date, format = "%m/%d/%Y"))

在我的输入文件中,仍在工作的员工的离职日期为空白,因为当然,他们还没有离职。如果日期列中有空白,R会变得混乱,因此我们将添加一行代码,为未来指定一个远期日期。

df <- employee_data %>%  mutate(Hire.Date = as.Date(Hire.Date, format = "%m/%d/%Y"),         Termination.Date = as.Date(Termination.Date, format = "%m/%d/%Y")) %>%  mutate(Termination.Date = if_else(is.na(Termination.Date),          as.Date("2100-12-31"), Termination.Date))

最后一行代码表示在终止日期列中有NA/空白的任何位置,都指定一个远期日期。在这种情况下,是2100年12月31日。希望我们都不要那时还在工作。

2. 计算每月员工人数

希望这一步看起来很简单,但是我在弄清楚它的过程中遇到了一些困难,所以请对自己有耐心。

首先,我们将创建一个序列,每个月都有一个日期,然后设置一个数据框作为我们每月员工人数的占位符,最后我们将使用sapply函数来计算每个月的员工人数。我们开始吧!

创建一个包含每个月日期的序列(例如,1/1/2023,1/2/2023等):

month_seq <- seq(from = min(df$hire_date),                 to = max(df$hire_date),                 by = "1 month")

这意味着从最早的入职日期开始,到最晚的入职日期结束,按月份进行排序。这样我们的数据中每个月都会有一个值。以下是它的样子:

显示每月序列。图片由作者提供。

现在我们要使用该序列创建一个起始数据框,然后在其中添加员工人数。

headcount_data <- data.frame(Date = month_seq)

好了,现在是棘手的部分。我们要计算headcount_data数据框中每个日期上活跃员工的数量。也就是说,在2020年1月1日、2020年2月2日等日期上有多少在职员工。

假设我们想计算2020年1月1日的情况。我们需要找出入职日期小于或等于2020年1月1日且离职日期大于2020年1月1日的员工数量。换句话说,已经入职但尚未离职的员工数量。

然后我们使用sapply在headcount_data的每个日期上进行计算。

headcount_data <- headcount_data %>%  mutate(Active.Employees = sapply(Date, function(x) {           sum(x >= df$hire_date & (is.na(df$termination_date) | x < df$termination_date))         }))

还跟上来了吗?如果你已经顺利完成到这一步,请给自己一个大大的鼓励!如果你遇到了问题,也给自己一个大大的鼓励,因为你已经走到这一步了,可以前往这里查看完整代码,看看你的代码是否有任何不一致之处。

3. 添加相关背景

这是故事叙述的部分。根据你对组织的熟悉程度和经验,你可能需要采访一些主题专家或资深员工。基本上,你想要添加有助于解释员工人数增加或减少的重要背景。

我想为每一年(也可以是每个月)添加背景,所以我要在headcount_data中添加一个年份列。

headcount_data <- headcount_data %>%   mutate(year = as.integer(year(Date)))

这将为每个日期添加一个年份列:

为每个日期添加了一个年份列。图片由作者提供。

现在,我们要为每年添加背景。假设我们想为2020年添加背景“COVID-19”,并希望在2020年的每个月都显示该背景。

为此,我们将使用case_when根据年份添加一个名为“context”的列。

headcount_data <- headcount_data %>%  mutate(context = case_when(    year == 2018 ~ "2018年的背景",    year == 2019 ~ "2019年的背景",    year == 2020 ~ "COVID-19",    TRUE ~ "没有其他背景"))

在上面的代码中,我们指定了当年份为2018的每一行中,我们希望上下文列的值为”2018的上下文”。您可以为感兴趣的每一年添加上下文,在TRUE子句中,您可以指定未在上面指定的任何年份的上下文应该是什么。

到目前为止,您的headcount_data应该是这样的:

已添加上下文列的数据集。作者提供的图片。

现在是有趣的部分!我们开始绘图。

4. 创建图表

首先,我们将使用ggplot创建一个包含所有数据的基本区域图。我们将在x轴上使用Date,在y轴上使用Active.Employees,以便我们可以看到随时间的人数变化。

headcount_data %>%  ggplot(aes(x = Date, y = Active.Employees)) +  geom_area()

这将给您一个基本的图表:

完整数据集的基本区域图。作者提供的图片。

现在我们开始一些基本的改进,然后再进行一些高级的改进:1. 添加注释 2. 添加标题和副标题

我们将添加以年份结尾的注释(当我们为每年制作图表时,这将变得更加相关)。让我们从将它们分配给变量开始,以便于每年更新:

# 注释annotation_ending_year <- max(headcount_data$year)annotation_ending_headcount <- max(headcount_data$Active.Employees)# 标题labels_title <- "我们的人数故事"labels_subtitle <- last(headcount_data$context)

现在我们将把它们添加到我们的基本图表中:

headcount_data %>%  ggplot(aes(x = Date, y = Active.Employees)) +  geom_area() +  labs(title = labels_title,       subtitle = labels_subtitle) +  annotate("text",            x = max(headcount_data$Date),           y = max(headcount_data$Active.Employees),           label = annotation_ending_headcount,           hjust = -.25)

这将为我们提供带有一些额外上下文的基本图表:

带有标题和注释的基本图表。作者提供的图片。

现在我们已经创建了基本图表,我们希望自动为每年创建一个加法图表。因此,会有从2018年到2018年末、从2018年到2019年末、从2018年到2020年末等等的图表。

5. 自动为每年创建一个图表

我们将使用for循环为数据集中的每一年创建一个图表。

基本上,我们将在名为”years”的向量中获取数据集中的每个唯一年份。然后对于”years”中的每个年份,我们将创建数据的子集,然后创建该子集的图表。这可能听起来令人困惑,但看看代码可能会更有意义。

首先进行一些设置:

# 创建一个唯一年份的向量years <- unique(headcount_data$year)# 用于存放图表的空列表plots <- list()

现在是循环的部分!它可能看起来很庞大,但只需一步一步来:

# 遍历years中的每个年份,并创建图表for (i in 2:length(years)) {  # 逐渐添加一年的子集  subset_df <- headcount_data %>%     filter(year <= years[i])    # 注释的计算  annotation_ending_year <- max(subset_df$Date)  annotation_ending_active <- subset_df %>%     filter(Date == ending_year) %>%     select(Active.Employees) %>%     as.numeric()    # 使用子集创建图表(p)  p <- subset_df %>%    ggplot(aes(x = Date, y = Active.Employees)) +    geom_area() +    labs(title = labels_title,         subtitle = labels_subtitle) +    annotate("text",              x = max(subset_df$Date),             y = max(subset_df$Active.Employees),             label = ending_active,             hjust = -.25)    # 保存每个图表  ggsave(p,          file = paste("example_plot_", years[i], ".png"),          height = 6, width = 8, units = "in")}

您现在应该在工作目录中保存了每年的一个图表,命名为“example_plot_year”。我喜欢每年都有一个单独的图表,这样我就可以将每个图表放在幻灯片中,并在人们有问题时暂停。或者,您可以将这些图表动画在一起,创建一个gif,或者使用像ScreenToGif这样的屏幕录制软件,得到类似以下的效果:

使用ScreenToGif制作的图表动画的gif。图片由作者提供。

我们做到了!!!唯一剩下的就是添加一些样式,使图表更符合您的品牌,并添加一个矩形突出显示最近的年份。

6. 调整主题和图表格式

我想要做的第一件事是添加一个矩形,突出显示最近的年份。这将帮助观众知道要关注的地方,并且每个图表中都会更新,因此我们可以一次查看一年的数据,而不会混淆整体情况。

我们可以通过添加另一个注释层“rect”来实现,大致如下:

annotate("rect", xmin = , xmax = , ymin = , ymax = )

这是我花了一些时间才达到自己想要的效果的另一个方面,关键在于:

X轴:我希望矩形从给定年份的第一个(即最早)日期(即数据子集中的最大年份)开始,并在给定年份的最后(即最晚)日期(即数据子集中的最大年份)结束。因此,对于2019年的图表,我们希望矩形从1/1/2019开始,到12/1/2019结束。

annotate("rect",           xmin = floor_date(max(subset_df$Date), "year"),           xmax = ceiling_date(max(subset_df$Date), "year")

Y轴:我希望矩形从y轴开始,并在该年份的最终人数上方结束,这样就更容易阅读,而不会拥挤。再次看看2019年,我希望矩形直接从y轴开始,到最终人数的上方(+300)结束,最终人数为240。

    annotate("rect",             xmin = floor_date(max(subset_df$Date), "year"),             xmax = ceiling_date(max(subset_df$Date), "year"),             ymin = -Inf, ymax = ending_active + 300)

样式:最后,我将使矩形变为灰色,并将alpha值设置为0.1,使其相对透明,您可以看到底部的面积图:

    annotate("rect",             xmin = floor_date(max(subset_df$Date), "year"),             xmax = ceiling_date(max(subset_df$Date), "year"),             ymin = -Inf, ymax = ending_active + 300,             alpha = .1, color = "gray", fill = "gray")

限制坐标轴:为了使过渡更平滑,我将对x轴和y轴设置限制,使每个图表的比例相同。

scale_x_date(breaks = "1 year", date_labels = "%Y",                 expand = c(.1,.1),                 limits = c(min(headcount_data$Date), max(headcount_data$Date)))

哇呜!我们离成功很近了,现在我要对主题进行一些更改,然后给自己倒一杯酒。现在是时候将自己的风格加入其中了,我的最终效果看起来可能是这样的:

最终产品!图片由作者提供。

这是我最终的for循环代码:

# 遍历每年的循环,创建图表for (i in 2:length(years)) {  # 逐年创建子集  subset_df <- headcount_data %>%    filter(year <= years[i])    # 注释计算  ending_year <- max(subset_df$Date)    ending_active <- subset_df %>%    filter(Date == ending_year) %>%    select(Active.Employees) %>%    as.numeric()    # 使用子集创建图表(p)  p <- subset_df %>%    ggplot(aes(x = Date, y = Active.Employees)) +    geom_area(fill = "#457b9d") +    labs(title = "我们的人数变化故事",         subtitle = paste(years[i],":", last(subset_df$context)),         x = "", y = "") +    scale_x_date(breaks = "1 year", date_labels = "%Y",                 expand = c(.1,.1),                 limits = c(min(headcount_data$Date), max(headcount_data$Date))) +    theme_classic(base_family = "Arial") +    theme(plot.title = element_text(size = 24, face = "bold", color = "#457b9d"),          plot.subtitle = element_text(size = 18),          panel.grid.major = element_blank(),          panel.grid.minor = element_blank(),          axis.ticks.y = element_blank(),          axis.text.y = element_blank(),          axis.line.y = element_blank()) +    annotate("text", x = ending_year,             y = ending_active, label = ending_active,             vjust = -1.25, hjust = -.25, color = "#457b9d") +    annotate("rect",             xmin = floor_date(max(subset_df$Date), "year"),             xmax = ceiling_date(max(subset_df$Date), "year"),             ymin = -Inf, ymax = ending_active + 300,             alpha = .1, color = "gray", fill = "gray")    # 保存每个图表  ggsave(p,         file = paste("example_plot_final", years[i], ".png"),         height = 6, width = 8, units = "in")  }

ALLLLLL DOOOOONNNNEEEE!

我们现在可以动态地查看我们的人数随时间的变化,副标题中还提供了一些背景信息。一些未来的改进想法:使用gganimate制作图表,为每年的人数变化添加百分比,如果人数增加或减少,改变图表的颜色,添加增长趋势线的预测等等,可能性无限!

你试过制作一个吗?如果是的话,我很想看看你的成果!

Github上的完整代码在这里。

想要更多关于人力资源分析的资源吗?

12个免费资源帮助你入门人力资源分析

我推荐给那些想要开始从事人力资源分析职业的人的免费资源。

jeagleson.medium.com

如果你想要更多这样的资源并且可以访问本站的所有精彩内容,你可以使用我的链接每月支付5美元(我将获得一小笔佣金,您不需要额外付费)。

阅读Jenna Eagleson(以及VoAGI上数千名其他作者的所有故事)。您的会员费直接支持…

jeagleson.medium.com

Jenna Eagleson 我的背景是工业与组织心理学,我在人力资源分析领域找到了我的归属。数据可视化使我的工作更有生命力。我喜欢学习和使用Power BI、R、Tableau等工具进行开发。我很想听听你的故事!请在Linkedin或Twitter上联系我。

Leave a Reply

Your email address will not be published. Required fields are marked *