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

如何解决药物持有率(MPR)计算问题?附代码实现疑问

解决药物持有率(MPR)计算的Clojure实现问题

我明白你现在在尝试用Clojure计算药物持有率(MPR),通过对比用药区间和观察期来得到比率。先看看你写的代码里几个需要调整的地方,然后咱们一起重构出更可靠的实现:

原代码的主要问题

  1. 全局变量滥用:你在函数内部用def定义start、end、start_date这些变量,这会创建全局状态,不仅容易导致数据混乱,也不符合Clojure函数式编程的理念,应该用let来创建局部绑定。
  2. 函数耦合性高:mpr_ratio完全依赖全局的start、end、observation_period,没法灵活处理不同的输入数据。
  3. 边界情况未处理:如果观察期天数为零,或者某个用药区间和观察期完全不重叠,代码会出现错误。

修正后的完整实现

咱们把代码拆成单一职责的小函数,用局部绑定替代全局变量,同时处理边界情况:

(ns clara-rules.mpr-new
  (:require [clj-time.core :as t]
            [clj-time.format :as f]))

;; 定义全局日期格式化器,避免重复创建
(def date-formatter (f/formatter "dd MM yyyy"))

;; 解析用药区间:把字符串日期转换成clj-time的日期对象
(defn parse-intervals [intervals]
  (map (fn [{:keys [start_ end_]}]
         {:start (f/parse date-formatter start_)
          :end (f/parse date-formatter end_)})
       intervals))

;; 计算观察期的总天数
(defn observation-period-days [start-str end-str]
  (let [start-date (f/parse date-formatter start-str)
        end-date (f/parse date-formatter end-str)]
    (t/in-days (t/interval start-date end-date))))

;; 核心MPR计算函数:返回每个区间的比率和总比率
(defn calculate-mpr [parsed-intervals obs-start-str obs-end-str]
  (let [obs-start (f/parse date-formatter obs-start-str)
        obs-end (f/parse date-formatter obs-end-str)
        obs-interval (t/interval obs-start obs-end)
        obs-days (t/in-days obs-interval)]
    (if (zero? obs-days)
      (throw (IllegalArgumentException. "观察期天数不能为零,请检查日期输入"))
      (let [;; 计算每个用药区间和观察期的重叠部分
            interval-overlaps (map (fn [{:keys [start end]}]
                                     (t/overlap obs-interval (t/interval start end)))
                                   parsed-intervals)
            ;; 处理无重叠的情况,默认0天
            overlap-days (map #(if % (t/in-days %) 0) interval-overlaps)
            ;; 计算每个区间的MPR比率(百分比)
            individual-ratios (map #(float (* (/ % obs-days) 100)) overlap-days)
            ;; 计算总MPR比率
            total-ratio (reduce + individual-ratios)]
        {:individual-ratios individual-ratios
         :total-ratio total-ratio}))))

;; ------------------- 使用示例 -------------------
(def sample-intervals
  '({:start_ "20 01 2012" :end_ "20 02 2012"}
    {:start_ "20 02 2012" :end_ "20 03 2012"}
    {:start_ "20 04 2012" :end_ "20 05 2012"}
    {:start_ "20 06 2012" :end_ "20 07 2012"}))

;; 解析示例区间
(def parsed-sample (parse-intervals sample-intervals))

;; 计算MPR(观察期:2012-02-01 到 2012-12-01)
(def mpr-result (calculate-mpr parsed-sample "01 02 2012" "01 12 2012"))

;; 输出结果
(println "每个用药区间的MPR比率(百分比):" (:individual-ratios mpr-result))
(println "总MPR比率(百分比):" (:total-ratio mpr-result))

代码说明

  • 局部绑定替代全局变量:所有临时变量都用let定义在函数内部,不会污染全局命名空间,数据更安全。
  • 单一职责函数:每个函数只做一件事,比如parse-intervals只负责解析日期,calculate-mpr专注于核心计算,代码更易维护和调试。
  • 边界处理:如果观察期天数为零,会抛出明确的异常;如果用药区间和观察期无重叠,自动按0天计算比率,避免nil错误。
  • 清晰的结果返回:返回一个包含individual-ratios(每个区间的比率)和total-ratio(总比率)的map,方便你后续使用这些结果。

运行这段代码后,你就能得到每个用药区间与观察期的MPR比率,以及所有区间的总比率啦。

内容的提问来源于stack exchange,提问作者CoDInG brO

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:16:51