【问题标题】:Aggregate daily data to calculate monthly average汇总每日数据以计算每月平均值
【发布时间】:2012-03-31 05:13:07
【问题描述】:

您好,我是 Python 的新用户,但在执行我认为相当基本的任务时遇到了问题。

我有几个 (>50) 个包含每日积雪深度数据的 csv 文件。我想遍历 csv 文件并计算雪深的每月平均值。数据示例:

Date,SD
1/1/2000,36
1/2/2000,36
1/3/2000,38
1/4/2000,40
2/1/2000,48
2/2/2000,48

换句话说,我想计算每月平均积雪深度并将输出写入一个新的 csv 文件。我能够为我的数据修改一个不同的代码示例,但是我收到了在我的字典中使用 Date 作为键值的键错误。

有什么建议吗?

到目前为止的代码:

from __future__ import division
import csv
from collections  import defaultdict

def default_factory():
    return [0, None, None, 0]

reader = csv.DictReader(open(r'C:\SandBox\VALIDATION\TestTable.csv'))

dates = defaultdict(default_factory)
for row in reader:
    sd = int(row["SD"])
    dates[row["Dates"]][0] += sd
    max = dates[row["Dates"]][1]
    dates[row["Dates"]][1] = amount if max is None else amount if amount > max else max
    min = dates[row["Date"]][2]
    dates[row["Dates"]][2] = amount if min is None else amount if amount < min else min
    dates[row["Dates"]][3] += 1

for date in dates:
    dates[date][3] = dates[date][0]/dates[date][3]

writer = csv.writer(open(r'C:\SandBox\VALIDATION\TestAvg.csv', 'w', newline = ''))
writer.writerow(["Date", "SD", "max", "min", "mean"])
writer.writerows([date] + dates[date] for date in dates)

编辑:澄清一下,我正在尝试实现每月平均值,即 1 月平均值、2 月平均值等...而不是计算单个日期的平均值。

【问题讨论】:

  • 你能发布整个堆栈跟踪/错误吗?
  • 如果你计算的是平均值而不是中值,你为什么要关心最小值和最大值?
  • 正如 WolframH 所说,您的 csv 的第一行是“Date,Snowdepth”,但您的代码正在寻找“Dates,SD”
  • jgritty,这只是我用作参考的一些代码的遗物。它是否在输出中并不重要。
  • 对于 jgritty:Traceback(最近一次调用最后一次):文件“C:\SandBox\Scripting\snotel.py”,第 17 行,在 dates[row["Dates"]][ 0] += sd KeyError: ('Dates',)

标签: python


【解决方案1】:

您可能希望使用字典使代码更具可读性。

from __future__ import division
import csv
from collections  import defaultdict

def default_factory():
   return { "sum": 0, "max": None, "min": None, "count": 0}

reader = csv.DictReader(open(r'sd.csv'))

dates = defaultdict(default_factory)
rows = []
for row in reader:
    date = row["Date"]
    sd = int(row["Snowdepth"])
    rows.append([date, sd])
    month = date.split("/")[0]
    r = dates[month]
    r["sum"] += sd
    max = r["max"]
    r["max"] = sd if max is None else sd if sd > max else max
    min = r["min"]
    r["min"] = sd if min is None else sd if sd < min else min
    r["count"] += 1

for date in dates:
    r = dates[date]
    r["avg"] = r["sum"]/r["count"]

writer = csv.writer(open(r'TestAvg.csv', 'w'))
writer.writerow(["Date", "SD", "max", "min", "mean"])
for row in rows:
    r = dates[row[0].split("/")[0]]
    writer.writerow(row + [r["max"], r["min"], r["avg"]])

【讨论】:

    【解决方案2】:

    您在某些地方使用Dates 作为列名(例如max = dates[row["Dates"]][1]),而在其他地方使用Date(例如min = dates[row["Date"]][2]),从您的数据示例看来Date 是列名?因此,如果您在任何地方都使用相同的名称,那应该没问题。

    s="""Date,Snowdepth
    1/1/2000,36
    1/2/2000,36
    1/3/2000,38
    1/4/2000,40
    2/1/2000,48
    2/2/2000,48"""
    
    import StringIO
    import csv
    reader = csv.DictReader(StringIO.StringIO(s))
    
    for row in reader:
        print row['Date']
    

    输出:

    1/1/2000
    1/2/2000
    1/3/2000
    1/4/2000
    2/1/2000
    2/2/2000
    

    【讨论】:

      【解决方案3】:
      from __future__ import division
      import csv
      from collections  import defaultdict
      
      def default_factory():
          return [0, None, None, 0]
      
      reader = csv.DictReader(open(r'snow_data.csv'))
      
      dates = defaultdict(default_factory)
      
      for row in reader:
          amount = int(row["Snowdepth"])
          dates[row["Date"]][0] += amount
          max = dates[row["Date"]][1]
          dates[row["Date"]][1] = amount if max is None else amount if amount > max else max
          min = dates[row["Date"]][2]
          dates[row["Date"]][2] = amount if min is None else amoun if amount < min else min
          dates[row["Date"]][3] += 1
      
      
      for date in dates:
          dates[date][3] = dates[date][0]/dates[date][3]
      
      writer = csv.writer(open(r'TestAvg.csv', 'w'))
      writer.writerow(["Date", "Snowdepth", "max", "min", "mean"])
      writer.writerows([date] + dates[date] for date in dates)
      

      我修复了代码以在任何地方使用 DateSnowdepth,这就是您的示例 csv 提供的内容。此外,您有一个变量amount,它原本是sd,否则未定义数量。我到处都做了那个amount

      除非您在一个日期有多个条目,否则它不会给出非常令人兴奋的结果。

      例如,以下是示例 csv 的输出:

      Date,Snowdepth,max,min,mean
      
      1/3/2000,38,38,38,38.0
      
      2/2/2000,48,48,48,48.0
      
      2/1/2000,48,48,48,48.0
      
      1/4/2000,40,40,40,40.0
      
      1/1/2000,36,36,36,36.0
      
      1/2/2000,36,36,36,36.0
      

      【讨论】:

      • 我想你误解了我的问题。我想达到月平均值(即 1 月平均值 36.6667)而不是日平均值。
      猜你喜欢
      • 1970-01-01
      • 2021-12-18
      • 2023-03-06
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      • 2017-11-10
      • 1970-01-01
      • 2023-03-13
      相关资源
      最近更新 更多