我需要使用PHP脚本在csv文件中计算从谷歌金融导入的股票价格的平均值和标准差。我可以将这些csv文件导入到mysql中的不同表中。我计划把每种存货都放在一张单独的桌子上,这样一开始就不那么复杂了。
在电子表格中,计算最后n行的运行平均值是相当容易的。然而,一旦我导入MySQL,我就会对如何计算从第20行开始的每一行的最后20行的平均值感到震惊(显然知识较少)。
当我从谷歌金融导入时,我的表结构如下:
+-------------+---------+
| id | close |
+-------------+---------+
| a1447128000 | 1353.5 |
| 1 | 1356.2 |
| 2 | 1352.65 |
| 3 | 1355.65 |
| 4 | 1354.2 |
| 5 | 1356 |
| 6 | 1351 |
| 7 | 1352.5 |
| 8 | 1350 |
| 9 | 1349.3 |
| 10 | 1343.6 |
| 11 | 1342.4 |
| 12 | 1340.7 |
| 13 | 1338.5 |
| 14 | 1340.5 |
| 15 | 1338.5 |
| 16 | 1340 |
| 17 | 1335.25 |
| 18 | 1340.5 |
| 19 | 1341 |
| 20 | 1338.95 |
| 21 | 1334 |
| 22 | 1326.5 |
| 23 | 1320.1 |
| 24 | 1318 |
+-------------+---------+
我正在努力实现这样的输出:
+-------------+---------+-----------+--------------------+
| id | close | average | standard deviation |
+-------------+---------+-----------+--------------------+
| a1447128000 | 1353.5 | | |
| 1 | 1356.2 | | |
| 2 | 1352.65 | | |
| 3 | 1355.65 | | |
| 4 | 1354.2 | | |
| 5 | 1356 | | |
| 6 | 1351 | | |
| 7 | 1352.5 | | |
| 8 | 1350 | | |
| 9 | 1349.3 | | |
| 10 | 1343.6 | | |
| 11 | 1342.4 | | |
| 12 | 1340.7 | | |
| 13 | 1338.5 | | |
| 14 | 1340.5 | | |
| 15 | 1338.5 | | |
| 16 | 1340 | | |
| 17 | 1335.25 | | |
| 18 | 1340.5 | | |
| 19 | 1341 | 1346.5975 | 6.885664002 |
| 20 | 1338.95 | 1345.87 | 6.886588415 |
| 21 | 1334 | 1344.76 | 6.921155973 |
| 22 | 1326.5 | 1343.4525 | 7.729917124 |
| 23 | 1320.1 | 1341.675 | 8.7418605 |
| 24 | 1318 | 1339.865 | 9.660513703 |
+-------------+---------+-----------+--------------------+
正如您正确地注意到的,对于第19行,平均值将是最后20行。对于行id 20,平均值将是最后20行。。。等等。
我甚至想知道php的foreach循环是否可以用于遍历每一行并获得最后20行的平均值,但当我尝试时,我完全迷失了方向。
我无法获得任何关于这方面的线索(无论是MySQL还是PHP)。如有任何关于如何解决此问题的建议,我们将不胜感激。
下面的代码大致显示了的功能
$averages = array();
while($row = $result->fetch_assoc())
{
$sum = 0;
$arraySize = array_push($averages,$row['close']);
if($arraySize > 20)
{
array_shift($averages)
}
foreach($averages as $value)
{
$sum += $value;
}
$average = $sum / $arraySize
}
从代码开头的一个空数组开始,在MySQL Results循环的每次迭代中,您都会使用array_push,它还会在添加值后返回数组的大小。然后检查这个值,如果它大于20,您会使用array_shift,它会将所有值下移1,去掉第一个值
如果您希望它在数组中的值数小于20时不进行计算,只需将foreach
及其下面的行包装在if语句中即可
$variableLoop=0;
while($row = $result->fetch_assoc())
{
$array[]=$row['close'];
if($variableLoop >= 19){
$result=0;
for($i=$variableLoop-19;$i<=$variableLoop;$i++){
$result+=$array[$i];
}
$average=$result/20;
//print or whatever you need to do with average and result
}
$variableLoop++;
}
不确定如何显示平均值,但这应该有效。
$values=array();$sum=0;$i=0;while($row=$result->fetch_assoc()){$values[]=$row[关闭];$sum+=$row[关闭];如果($i>19){$sum-=$values[$i-20];$row[‘average’]=$sum/20;}}
这是对我有用的完整代码。感谢@Memor-X、@origenes和@Terminus,因为这段代码是使用他们的响应开发的。我甚至用同样的逻辑计算了标准偏差。
$averages = array();
while($row = $result->fetch_assoc())
{
$sum = 0;
$arraySize = array_push($averages,$row['close']);
if($arraySize > 20)
{
array_shift($averages);
}
if($arraySize > 19) {
$sum = array_sum($averages);
$average = $sum /20;
echo "average: " .$average ."<br/>";
}
$sumOfDiff =0;
if($arraySize > 19) {
foreach($averages as $valueitem)
{
$sumOfDiff += ($valueitem - $average)*($valueitem - $average);
}
$variance = $sumOfDiff/20;
$stddev = sqrt($variance);
$upperband = $average + ($stddev *2);
$lowerband = $average - ($stddev *2);
echo "variance: " .$variance."<br/>";
echo "standard deviation: " .$stddev ."<br/>";
}
}