【问题标题】:How can I convert several NumPy arrays with ints to a NumPy array with formatted strings?如何将多个带有整数的 NumPy 数组转换为带有格式化字符串的 NumPy 数组?
【发布时间】:2022-01-01 09:04:50
【问题描述】:

我有三个包含整数的长度相同的数组:yearsmonthsdays。我想创建一个长度相同的 (NumPy) 数组,其中包含格式为 '(-)yyyy-mm-dd' 的字符串,格式为 '%i-%2.2i-%2.2i'

对于标量情况,我会做类似的事情

year=2000; month=1; day=1
datestr = '%i-%2.2i-%2.2i' % (year, month, day)

这将产生'2000-01-01'

我怎样才能创建这个的矢量版本,例如:

import numpy as np
years  = np.array([-1000, 0, 1000, 2000])
months = np.array([1, 2, 3, 5])
days   = np.array([1, 11, 21, 31])
datestr_array = numpy.somefunction(years, months, days, format='%i-%2.2i-%2.2i', ???)

请注意,我感兴趣的日期范围介于 -2000 年和 +3000 (CE) 年之间,因此 Python 的 datetime 和 Pandas 的 DateTimeIndex 都没有提供解决方案。

【问题讨论】:

  • datastr_array = ['%i-%2.2i-%2.2i'.format(years[j], months[j], days[j]) for j in range(len(years))] - 虽然这看起来很复杂,但实际上只是格式化,但需要多次。
  • 你说得对,我认为这可能是一种可能的方式,但看起来总是返回数组的字符串副本。
  • 快速编译的代码主要适用于数字,而不是字符串
  • Dw @AstroFloyd - 看看下面的代码 - 它修复了一切
  • 这样的功能已经是not yet implemented for the datetime type,所以显然不适用于多个数组(Numpy 中还没有通用格式化功能)。我想知道是否有一些技巧可以在没有循环的情况下手动获得类似的结果,但是 Numpy 中的字符串处理非常有限,所以我认为最好的方法可能是使用循环或 C/Cython 模块(生成一个 Numpy 数组,因为使用纯 Python 字符串不会更快)。

标签: python arrays string numpy formatting


【解决方案1】:

简单的列表推导会比numpy 函数更快:

['%i-%2.2i-%2.2i'%(y,m,d) for y,m,d in zip(years, months,days)]

对于数据框

arr = df[['year','month','day']].values   # a (n,3) array
['%i-%2.2i-%2.2i'%(y,m,d) for y,m,d in arr]

添加arr=arr.tolist() 可能会增加一些速度,因为列表的迭代速度比数组快。

【讨论】:

    【解决方案2】:

    说明

    让我们创建一个函数,将 any 日期无限制地转换为 yyyy-mm-dd 字符串。我们可以使用字符串格式化,在这里我们创建一个预定义的字符串并简单地格式化相关数据。我们还需要将长度格式化为在前面有零以“填写”,即 2001-05-20

    为了能够运行此函数,必须将所有相应的年份、月份和日期组合在一起,这可以通过 zip 函数来实现,该函数将列之间的行分组为元组。最好将其转换为numpy 数组。

    现在我们有了正确的元组形式的数据,让我们通过我们的函数解析它。我们可以使用apply 创建一个新数组,即numpy.apply_on_axis(func, axis, data)。因为元组在第二个轴,所以轴参数必须设置为1。

    代码

    def FormatDate(data):
        # Where data is a tuple for y, m, d
        return "{0:04}-{1:02}-{2:02}".format(data[0], data[1], data[2]) # Note that this formatting can later be update to account for some weirdness
    
    # Convert the data into tuples where y, m, d are aligned in rows
    converted = numpy.array(list(zip(years, months, days)))
    
    # Now, lets apply that function to make the tuples all dates
    datestr_array = numpy.apply_along_axis(FormatDate, 1, converted)
    

    【讨论】:

    • 如果您需要解释,请添加评论。
    • 谢谢拉里。然而,Python 的datetime 给了我一个ValueError: year -1000 is out of range。我认为datetime 不相信世界存在于公元 1 年之前,DateTimeIndex 甚至不相信中世纪......
    • @AstroFloyd 已编辑 - 它可以处理极端日期和负数.. 编辑:连字符可能有点混乱 - 您可以通过使用 . 等编辑现有的连字符来更改它。 - 如"{0:04}.{1:02}.{2:02}"
    • @LarrytheLlama 很好的解决方案,但我认为你应该改变轴: 0 到 1 在 \datestr_array = numpy.apply_along_axis(FormatDate, 0, converted)\ 。然后它会很好用!
    • df[['year','month','day']].values 将是一个类似converted 的数组。 pandas 可能有一些 str 功能使这更容易。它在对象 dtype Series 中使用 python 字符串。我见过人们使用某种df.str 代码,但我自己什么都没做。
    猜你喜欢
    • 2021-12-31
    • 1970-01-01
    • 2019-01-24
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 2011-03-11
    相关资源
    最近更新 更多