python - 如何使用 nditer 和 multi-index 索引到两个不同的数组并构建一个新数组
问题描述
我想使用 python/pandas/numpy 访问一个数组(df2)(实际上是一个 pandas 数据框)以基于条件语句索引到另一个数组(df)并在附加标签的同时构建一个新数组(New)。
这是我想为我正在从事的课程项目构建的数据清理例程。通常我会使用 Matlab 来解决这样的问题,但不幸的是我现在无法访问。到目前为止,我已经尝试过以下代码: 1) 创建一个名为 df 的随机值数据框。2) 创建第二个数据框,它是 df1 的五行的百分比增加,称为 df2。3) 查看 df2 中的所有值,并根据这些值 - 使用条件语句 - 创建一个名为 New 的新数据框。New 由 df 切片以及基于百分比变化的标签组成(标签是在循环中使用 if 语句创建的,如下所示)。另外,请注意定义 df 中切片的索引与 df2 中的索引不同,而是通过简单的移位相关联。
import pandas as pd
import numpy as np
import matplotlib as plt
df = pd.DataFrame(np.random.randn(100, 10)) #Create random dataframe
df
df2=df.pct_change(5) #Create a related dataframe df2
New=[] #Create an empty dataframe to build my new dataframe
it=np.nditer(df2, flags=['multi_index'])
while not it.finished:
i=it.multi_index(0,0)
k=it.multi_index(0,1)
ii=i-10
end=ii-5
if df2.iloc[i,k]>1:
New=df.iloc[ii:end,k].append(1, ignore_index=true)
elif df2.iloc[i,k]>.5:
New=df.iloc[ii:end,k].append(2, ignore_index=true)
elif df2.iloc[i,k]>.25:
New=df.iloc[ii:end,k].append(3, ignore_index=true)
elif df2.iloc[i,k]>0:
New=df.iloc[ii:end,k].append(4, ignore_index=true)
elif df2.iloc[i,k]>-.05:
New=df.iloc[ii:end,k].append(5, ignore_index=true)
else:
New=[]
Labeled=New
Final=Labeled.append(New, ignore_index=true)
it.iternext()
我期待我会得到一个名为 New 的数组,它有 6 行 950 列,其中第 6 行是标签,第 1 - 5 行是来自 df1 的切片。我在运行代码时得到的输出是:
--------------------------------------------------------------------
-------
TypeError Traceback (most recent
call last)
<ipython-input-7-3743c76c2bd6> in <module>()
10 it=np.nditer(df2, flags=['multi_index'])
11 while not it.finished:
---> 12 i=it.multi_index(0,0)
13 k=it.multi_index(0,1)
14 ii=i-10
TypeError: 'tuple' object is not callable
所以很明显我对 multi_index 的使用并不完全正确。阅读 nditter 手册后,我的期望是 it.multi_index 将是一个 1X2 数组,然后我可以使用它来关联两个数据帧之间的索引并用于创建 df 切片。另外,我知道这种类型的迭代在 Python 中是不可取的,因为它很慢,但我无法找到一种方法来矢量化这个例程,因为索引是偏移的,并且创建的最终数据帧不同于任何一个的输入数组。无论如何,任何指针将不胜感激。谢谢!
解决方案
查看基本的 multi_index,https: //www.numpy.org/devdocs/reference/arrays.nditer.html#tracking-an-index-or-multi-index
In [109]: it = np.nditer(np.ones(12).reshape(3,4), flags=['multi_index'])
In [110]: with it:
...: while not it.finished:
...: print(it.multi_index)
...: it.iternext()
...:
(0, 0)
(0, 1)
...
(2, 2)
(2, 3)
请注意,这it.multi_index
是一个元组。这是你错误的直接来源
i=it.multi_index(0,0)
(0,0)
是用于调用函数的 Python 语法,而不是索引(与 MATLAB 的用法相反)。multi_index
也不是二维数组,所以也[0,0]
无效。
这应该可以解决眼前的问题:
11 while not it.finished:
12 i=it.multi_index[0]
13 k=it.multi_index[1]
# i, k = it.multi_index # using unpacking
14 ii=i-10
我想知道你为什么使用nditer
. 我从未见过它应用于数据框。
In [119]: df2.shape
Out[119]: (100, 10)
In [120]:
In [120]: it = np.nditer(df2, flags=['multi_index'])
In [121]: it.multi_index
Out[121]: (0, 0)
In [122]: it.iternext()
Out[122]: True
In [123]: it.multi_index
Out[123]: (1, 0)
In [124]: it.iternext()
Out[124]: True
In [125]: it.multi_index
Out[125]: (2, 0)
如果我让它运行到最后,最后一个元组将是 (99,9)。所以这和做的一样
for i,k in np.ndindex(df2.shape):
....
但这并不能说明太多,因为它是在 Python 级别使用 ndindex
的少数几个地方之一。如https://www.numpy.org/devdocs/reference/arrays.nditer.html中所述,主要是在或其他编译代码中使用它的垫脚石。在 Python 级别上,它提供的不多,当然也没有任何速度。nditer
nditer
cython
或等效地:
for i in range(100):
for k in range(10):
# do stuff with i,k
另一个问题
New=[]
这是一个空列表。我们经常通过增加一个列表来创建一个数组
alist = []
for ....:
alist.append(avalue)
arr = np.array(alist)
我不确定这些行:
New=df.iloc[ii:end,k].append(1, ignore_index=true)
New
这为替换之前的任何内容分配了一个新值。我不熟悉pandas
df[].append(...) . If it were the numpy
np.append(new, x)`,我会尖叫血腥谋杀。
我更关注numpy
,但我认为有更好的方法来迭代数据框。 nditer
不是一个好的通用迭代工具。 pandas
人们似乎使用了apply
相当多的。
推荐阅读
- python - 检查是否存在重复,然后在行中附加一个唯一的数字?
- .net - CLR 是否在 JIT 编译期间进行类似数据库的查询?
- r - 在 R Shiny 应用程序 UI 出现之前让服务员功能运行
- excel-formula - 在 Excel 中使用多项式回归
- django - Django 在尝试创建 postgresql 数据库时抛出“[12728] 错误:CREATE DATABASE 无法在事务块内运行”
- sql - 这两个存储过程之间是否存在功能差异?
- java - 为什么我的 java 应用程序在服务器上看不到 mariadb 驱动程序,即使它在本地运行良好?
- python - 绘制 dataFrame 中所有值的直方图
- python - 删除 Pandas 列中所有大于一的空格
- javascript - 学习 JS ......似乎被困在这个练习中......不知道我做错了什么