【问题标题】:find out the most commonly occurring date interval from a set of varying date intervals in python [closed]从python中的一组不同日期间隔中找出最常见的日期间隔[关闭]
【发布时间】:2016-04-06 11:09:54
【问题描述】:

我有一个 CSV 文件,其中包含一百万条记录的不同日期范围的列。例如,我有这样的事情: 2004-2016; 1980-2016; 1991-2006; 2000-2012; 1998 - 2011

如果我想找出所有这些记录中最常见的 3、5 或 7 年范围,我将如何在 Python 中执行此操作?是否消除了一些记录并不重要,但我试图找出所有范围内最常见的 7 年频率或 10 年频率。有人可以帮忙吗?

【问题讨论】:

  • 如何加载数据?在['2004-2016', '1980-2016', ...]? 之类的列表中
  • 您究竟需要什么帮助?你试过什么,你在哪里卡住了?你写过代码吗?

标签: python date daterangepicker


【解决方案1】:

您可以使用collections.defaultdictcollections.Counter 来处理此问题。 defaultdict 用于按年数对日期范围进行分组,Counter 用于跟踪该年数的范围字符串计数:

from collections import defaultdict, Counter

year_ranges = defaultdict(Counter)

s = '2004-2016; 1980-2016; 1991-2006; 2000-2012; 1998 - 2011; 2004-2016'
for start, end in [r.split('-') for r in s.split('; ')]:
    start, end = int(start), int(end)
    year_ranges[end-start].update(['{}-{}'.format(start, end)])    # update counter for normalised range string

>>> print(year_ranges)
defaultdict(<class 'collections.Counter'>, {36: Counter({'1980-2016': 1}), 12: Counter({'2004-2016': 1, '2000-2012': 1}), 13: Counter({'1998-2011': 1}), 15: Counter({'1991-2006': 1})})

如果您想知道年份范围为 12 的最常见范围字符串:

>>> year_ranges[12].most_common(1)
[('2004-2016', 2)]

不确定如何处理存在多个范围字符串表示相同年份范围且计数相同的情况。

【讨论】:

  • @Reti43:因为eval 对不受信任的数据很危险。它也很慢,有100万条记录。我展示的方法还有一个优点是日期范围字符串在被计算之前被标准化,例如1998 - 20111998-2011被认为是相同的。
  • @Reti43:try 语句如何防止执行任意代码?如果输入是恶意的,但eval() 可以执行的有效代码,则不会引发异常。如果数据包含os.system('rm -rf /tmp')(或更糟)怎么办?一般来说,使用eval() 是个坏主意。它比我展示的直接字符串操作慢 4-6 倍。而且您仍然必须对输入字符串进行规范化以获得合理的计数。
  • 我不坚持eval()。您还提出了一个很好的观点,即它更快。但是,假设输入错误的可能性,int() 可能会失败。
  • @Reti43:很公平,int() 也可能因输入错误而失败——尽管它不太可能用它来破坏你的文件系统。不过我同意你的观点,我在这些 cmets 中的主要观点是 eval() 是一个不必要的冒险解决方案。
  • 我完全支持你。我太天真了。
【解决方案2】:
  • 解析文件;获取 2 元素元组:((2004, 2016), (1980-2016), ...)
  • 将其转换为差异:(12, 36, ...)
  • 使用此序列创建Counter 对象并调用most_common 方法。

【讨论】:

    【解决方案3】:

    将您的序列分成单独的范围。假设您调用生成的序列差异。

    from collections import Counter
    
    diff = ["2004-2016", "1980-2016", "1991-2006", "2000-2012", "1998 - 2011"]
    
    diff_frequency = Counter( map( lambda x: abs( eval(x) ), diff) ).most_common()
    
    most_common_diff = diff_frequency[0]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-26
      • 2013-03-04
      • 1970-01-01
      • 2017-10-27
      • 1970-01-01
      相关资源
      最近更新 更多