【问题标题】:Graphing average actions per minute绘制每分钟的平均操作数
【发布时间】:2011-11-14 20:43:47
【问题描述】:

我正在使用 google 图形库在 php 中创建一个图表来显示 StarCraft II APM 数据,但我无法思考这一切的逻辑。我不确定这是最好的提问地点,但我别无选择。这有点难以解释,所以如果需要任何澄清,请告诉我。

我有一组键和值。关键是以秒为单位的时间。该值是那一秒执行的操作。我的数据源省略了 0 个动作的秒数。 示例:

seconds     actions
1           10
3           5
4           7
7           15
etc         etc

我想要做的是绘制这些数据,显示每分钟的平均操作数,每隔一秒的时间间隔。直到第一分钟,我都会使用已经过去的可用秒数。

这是我当前的代码

$p1_total = 0;
foreach ($p1 as $seconds => $actions) {
    $p1_total = $p1_total + $actions;
    $data['player1'][$seconds] = round($p1_total * 60 / $seconds);
}

然而,这会计算一个滚动平均值,因为它会继续加起来 $p1_total,我真正需要的是每个时间间隔过去 60 秒的平均值。

我只是无法理解如何干净地编写代码。我知道我需要用过去 60 秒的操作数替换 $p1_total。但收集这就是让我感兴趣的东西。我应该如何在不处理大量变量的情况下动态设置它?请记住,我的秒数不是每秒,所以我不能只抓取数组中的最后 60 个条目,因为它们可能超过 60 秒。

我曾考虑在数组中插入值来弥补空白点,但如果不使平均值偏斜,我想不出任何合理的方法。 或者有什么方法可以让我在数学上更干净。

我感谢所有可以提供帮助的人。如果有更多信息有帮助,请告诉我。从表面上看,这感觉是一个非常简单的问题,但它确实被难住了。 :(

【问题讨论】:

  • 只是为了正确理解,密钥从1 开始并继续超过60?所以在时间t 你想要从max(0,t-60)t 的所有键,然后对相应的值(动作)求和?
  • 是的。键从 1 开始,可以继续输入任何数字。它通常不会超过一个小时,但不能保证。我基本上需要每组60的总和。 1-60、2-61、3-62 等。但是由于缺少一些值,我不能只抓住这 60 个键。 :(

标签: php math graph


【解决方案1】:

您可以插入零来弥补空白点,因为数据中未表示的每次都对应于执行零操作的一秒。这可能是概念上最简单的方法。您不需要实际上插入零;你可以做的是创建一个函数,如果它存在则返回$p1[$t],否则返回0。然后只需使用你的函数而不是直接访问$p1。 (我的 PHP 已经很生疏了,所以如果有必要可以考虑这个类似 PHP 的伪代码)

function actions_at_second($t) {
    return ($t in $p1) ? $p1[$t] : 0;
}

请记住,即使您在某些秒内没有原始数据,这些秒内的总操作计数仍将是非零的。因此,您应该每秒在最终的 APM 数组中创建一个数据点,无论当时是否执行了任何操作。

至于实际计算滚动平均值,您可以做的是迭代前 60 秒并将累积总数存储在输出数组中:

for ($t = 1; $t <= 60; $t++) {
    $total += actions_at_second($t);
    $data['player_1'][$t] = $total * 60 / $t;
}

(如果您的原始数据包含零秒的条目,则需要进行调整)然后在前 60 秒后,每次添加给定秒的操作数时,减去 60 秒前执行的操作数:

for ($t = 61; $t <= $tmax; $t++) {
    $total += actions_at_second($t) - actions_at_second($t - 60);
    $data['player_1'][$t] = $total;
}

$tmax 将是您拥有数据的最高秒数,基本上是游戏的长度。)我想在后一个示例中,$total 不再代表完整的累积总数,因此您可以重命名它 -但它必须与前面代码示例中的 $total 相同。

顺便说一句,我假设$tmax 永远不会小于 61。如果您要“公开”发布此代码供其他人使用,请确保检查这种情况(以防提前投降之类的)。

【讨论】:

    【解决方案2】:

    这将循环遍历数组并且只添加max(0,$current_time-60)和$current_time. To get the average you need to divide by$current_time - $start_timewhich will be60or$current_timeif$current_timeis less than60`之间的动作。

    // $p1 is array of seconds => actions
    
    $current_time = 75;
    $start_time = max(0,$current_time-60);
    
    $total_actions = 0;
    foreach($p1 as $key => $value) {
      if( $start_time < $key && $key <= $current_time )
        $total_actions += $value;
    }
    $average = $total_actions / ($current_time - $start_time);
    

    【讨论】:

      猜你喜欢
      • 2021-06-16
      • 2020-05-19
      • 1970-01-01
      • 2019-02-09
      • 2012-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多