【问题标题】:Assigning Indices in array to Months and Years将数组中的索引分配给月份和年份
【发布时间】:2021-10-18 23:23:16
【问题描述】:

我需要制作一个可以接收数字的函数,在数据文件(太阳黑子)中搜索该数字并返回相关索引作为月份和年份。

逻辑如下:索引0对应Jan, 1749,最后一个索引对应Dec, 1983。月份随着索引的增加而循环,然后每次达到第 n*12 个索引时,年份都会递增。

到目前为止我的代码是:

count = float(input("Enter a number of sunspots: "))
def get_year_and_month(count):
    x = sunspots
    if any(x == count):
        print(np.where(x == count))
get_year_and_month(count)

返回:

Enter a number of sunspots: 58
(array([   0,  516, 1591], dtype=int64),)

索引0 的预期输出是Jan, 1749,然后是第516 和第1591 索引的月份和年份。

有没有好办法把索引改成上面提到的格式?

【问题讨论】:

  • 预期输出是什么?
  • 预期输出是:1749 年 1 月,然后是第 516 和第 1591 索引的月份和年份。考虑到月份循环,然后每次达到第 n12 个索引时 +1 到年份
  • 对不起,如果这很难理解。一般来说,我是编码新手,如果没有完整的词汇表,我很难表达我想要做的事情

标签: python arrays python-3.x numpy lookup


【解决方案1】:

字符串作为索引在 NumPy 数组中是不可能的。

但是,如果我理解正确,您实际上并没有必要更改索引,而只是想根据索引获取相应的月份和年份。

从索引中计算正确的月份和日期非常简单。为此,您可以使用 modulusfloor division 函数。

由于年份每 12 个指数递增,您可以将其计算为 1749(基准年)加上指数的下限除以 12 的结果:

yr = idx // 12 + 1749

月份是索引模 12 加一(因为索引从零开始):

mnth = idx % 12 + 1

由于您不希望将月份作为数字,而是将缩写作为字符串,因此您需要将不同的可能性之一应用于get the month name from a number。我只是创建了一个数组来查找月份缩写,如this SO answer,因为以后可以有效地使用它来查找np.take()

months = ['n/a', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

mnth_abbrev = months[idx % 12 + 1]

为了不仅将其有效地应用于单个索引值,而且同时应用于 numpy 数组的所有值,我们可以使用针对性能优化的上述操作的 矢量化 版本。它们是np.mod()(用于%)和np.floor_divide()(用于//)。此外,我们使用np.take()(对于x[y],请参阅this SO post)。作为一些小的更改,我使用np.flatnonzero() 而不是np.where() 来获取索引,因为我们想要一个数组作为结果而不是一个元组(有关更多信息,请参阅this SO post)。最后,我使用np.char.add() 连接月份和年份,还稍微更改了months 数组,在每个月份缩写后包含一个逗号和一个空格,以获得最终所需的输出。

完整示例:

import numpy as np

sunspots = np.array([58,12,4,0,58,1,548,45,0,0,2,58,58,1,12,2,0,58])

months = ['n/a', 'Jan, ', 'Feb, ', 'Mar, ', 'Apr, ', 'May, ', 'Jun, ', 'Jul, ', 'Aug, ', 'Sep, ', 'Oct, ', 'Nov, ', 'Dec, ']


def get_year_and_month(cnt, spots):
    hits = np.flatnonzero(spots == cnt)
    mths = np.take(months, np.mod(hits, 12) + 1)
    yrs = np.floor_divide(hits, 12) + 1749
    return np.char.add(mths, yrs.astype('str'))

count = int(input("Enter a number of sunspots: "))

res = get_year_and_month(count, sunspots)

if res.size != 0:
    print(np.vstack(res))

输出:

Enter a number of sunspots: 58
[['Jan, 1749']
 ['May, 1749']
 ['Dec, 1749']
 ['Jan, 1750']
 ['Jun, 1750']]

对于您的数据,结果将是:

Enter a number of sunspots: 58
[['Jan, 1749']
 ['Jan, 1792']
 ['Aug, 1881']]

如果您经常/重复调用此函数,另一种方法是将完整日期范围构造为数组并通过它查找索引:

import numpy as np

sunspots = np.array([58,12,4,0,58,1,548,45,0,0,2,58,58,1,12,2,0,58])

months = ['n/a', 'Jan, ', 'Feb, ', 'Mar, ', 'Apr, ', 'May, ', 'Jun, ', 'Jul, ', 'Aug, ', 'Sep, ', 'Oct, ', 'Nov, ', 'Dec, ']

dates = np.arange(0,sunspots.shape[0])
dates = np.char.add(np.take(months, np.mod(dates, 12) + 1), (np.floor_divide(dates, 12) + 1749).astype('str'))

def get_year_and_month(cnt, spots, dts):
    hits = np.flatnonzero(spots == cnt)
    return np.take(dts, hits)

count = int(input("Enter a number of sunspots: "))

res = get_year_and_month(count, sunspots, dates)

if res.size != 0:
    print(np.vstack(res))

输出与上面的相同。


如果你真的确实想要一个带有字符串索引的数据结构,我建议你使用Pandas DataFrame。你可以例如只需以相同的方式构建日期数组并将其作为DataFrame() 调用的index 参数传递。然后通过df.index 查找您的结果:

import numpy as np
import pandas as pd

sunspots = np.array([58,12,4,0,58,1,548,45,0,0,2,58,58,1,12,2,0,58])

months = ['n/a', 'Jan, ', 'Feb, ', 'Mar, ', 'Apr, ', 'May, ', 'Jun, ', 'Jul, ', 'Aug, ', 'Sep, ', 'Oct, ', 'Nov, ', 'Dec, ']

df = pd.DataFrame(data=sunspots, index=np.char.add(np.take(months, np.mod(np.arange(sunspots.shape[0]), 12) + 1), (np.floor_divide(np.arange(sunspots.shape[0]), 12) + 1749).astype('str')), columns=['spots'])

count = int(input("Enter a number of sunspots: "))

print(df.index[df['spots'] == count].tolist())

输出:

Enter a number of sunspots: 58
['Jan, 1749', 'May, 1749', 'Dec, 1749', 'Jan, 1750', 'Jun, 1750']

由于数据框现在确实将日期字符串作为索引,您还可以通过此字符串索引访问您的太阳黑子数据:

>>> df
           spots
Jan, 1749     58
Feb, 1749     12
Mar, 1749      4
Apr, 1749      0
May, 1749     58
Jun, 1749      1
Jul, 1749    548
Aug, 1749     45
Sep, 1749      0
Oct, 1749      0
Nov, 1749      2
Dec, 1749     58
Jan, 1750     58
Feb, 1750      1
Mar, 1750     12
Apr, 1750      2
May, 1750      0
Jun, 1750     58

>>> df['spots']['Jan, 1750']
58

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 2015-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多