You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中用循环创建哑变量统计各城镇年度门店数量

问题描述

我是R语言初学者,问题比较基础还请见谅。我现在有个包含各城镇门店开业、闭店日期的数据集,需要统计各城镇每年的门店数量。之前我问过这个问题,得到了热心帮助但没实现别人的方案,不过理解过程中学到了很多,自己想了一套方法:

  • 为每一年创建哑变量,标记门店当年是否营业;
  • 用pivot_longer()转换数据格式;
  • 通过group_by()和summarise()统计数量。

我手动写了示例代码,但数据年份跨度是1900-2023,手动创建哑变量效率太低,想请教怎么用循环批量创建这些哑变量。

手动实现代码

数据初始化

library(tidyverse)
library(stringr)
library(lubridate)

id <- c("001", "002", "003", "004")
town <- c("A", "A", "A", "B")
opening <- as.Date(c("1900-01-01", "1902-02-05", "1903-01-01", "1903-01-01"))
closing <- as.Date(c(NA, NA, NA, "1905-03-03"))

df <- data.frame(id, town, opening, closing)

手动创建哑变量及后续处理

df_intermediate_1 <- df %>% 
  mutate(Year_1900 = if_else(opening <= 1900 & closing > 1900, TRUE, FALSE),
         Year_1901 = if_else(opening <= 1901 & closing > 1901, TRUE, FALSE),
         Year_1902 = if_else(opening <= 1902 & closing > 1902, TRUE, FALSE),
         Year_1903 = if_else(opening <= 1903 & closing > 1903, TRUE, FALSE),
         Year_1904 = if_else(opening <= 1904 & closing > 1904, TRUE, FALSE),
         Year_1905 = if_else(opening <= 1905 & closing > 1905, TRUE, FALSE))

df_intermediate_2 <- df_intermediate_1 %>% 
  pivot_longer(
    cols = c("Year_1900","Year_1901","Year_1902","Year_1903","Year_1904","Year_1905"),
    names_to = 'year',
    values_to = 'is_open')
  
df_output <- df_intermediate_2 %>% 
  group_by(town, year) %>% 
  summarise(stores = sum(is_open))

df_output$year <- as.numeric(substr(df_output$year, start = 6, stop = nchar(df_output$year)))
解决方案

方法一:循环批量创建哑变量

首先定义年份范围,然后通过for循环批量生成每个年份的哑变量,同时修正原代码中未处理closing为NA(门店持续营业)的问题:

# 定义年份范围
years <- 1900:2023

# 初始化中间数据框
df_intermediate_1 <- df

# 循环创建哑变量
for (y in years) {
  # 生成列名
  col_name <- paste0("Year_", y)
  # 添加哑变量:开业年份<=当前年,且(未闭店或闭店年份>当前年)则标记为营业
  df_intermediate_1 <- df_intermediate_1 %>%
    mutate(!!col_name := if_else(opening <= y & (is.na(closing) | closing > y), TRUE, FALSE))
}

# 转换数据格式(无需手动列所有年份列,用starts_with匹配)
df_intermediate_2 <- df_intermediate_1 %>% 
  pivot_longer(
    cols = starts_with("Year_"),
    names_to = 'year',
    values_to = 'is_open')

# 统计各城镇每年门店数量,并简化年份格式
df_output <- df_intermediate_2 %>% 
  group_by(town, year) %>% 
  summarise(stores = sum(is_open), .groups = "drop") %>%
  mutate(year = as.numeric(str_remove(year, "Year_")))

方法二:更高效的无哑变量方案(推荐)

对于年份跨度大的场景,创建大量哑变量会占用过多内存,推荐直接生成每个门店的营业年份序列再统计,效率更高:

df %>%
  rowwise() %>%
  # 生成该门店所有营业年份的序列:从开业年份到闭店年份(未闭店则到当前年)
  mutate(year = list(seq(year(opening), year(coalesce(closing, today())), by = 1))) %>%
  # 展开年份序列
  unnest(year) %>%
  # 按城镇和年份分组统计门店数
  group_by(town, year) %>%
  summarise(stores = n(), .groups = "drop")

内容的提问来源于stack exchange,提问作者L.P. Hayek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:58:09