【问题标题】:During a loop in which I append indexes to a list, said list of indices changes from list to numpy array在我将索引附加到列表的循环期间,所述索引列表从列表更改为 numpy 数组
【发布时间】:2024-04-30 11:10:02
【问题描述】:

我将首先介绍一下我尝试使用此产品实现的目标。我需要过滤CSV 文件并在文件中的任何位置搜索某些关键字。它在哪一列对项目来说并不重要。目标是获取符合条件的行的索引。通过该列表,我们将确定哪些行与我们正在进行的搜索相关,哪些行与搜索无关。

问题与我们在循环期间将数据附加到更改类型的列表有关。在循环结构中,我写过,存储信息的列表会运行几次,然后从列表变为NumPy array。这会导致错误和代码中断。我已经输入了一些 try 和 except 语句来查找错误发生的位置。

您将在下面找到我用来尝试查找相关索引的循环。该类型由整个循环中的打印语句跟踪。我用 cmets 来解释我在这段代码中使用的一些打印语句的基本原理。第一个循环行中引用的 Data 是 CSV 的数据框。

import pandas as pd
import numpy as np
data = pd.read_csv('./real_acct.txt', delimiter = "\t")
index_list = []
print(type(index_list))
#--------------------------------------
for col in data:
    df_loop = data[data[col].astype(str).str.contains("SOME VAL", na = False)] # find the key word in each column on the loop
    print(type(index_list)) # this is so I can see what the type of the index list is
    print('col loop') # this lets me know that I am in the column loop
    print('------------') 
    if(df_loop.shape[0] > 0):
        list_ind = list(df_loop.index.values)
        print('shape is greater than 1x1') # df_loop found a value that contains the text
        print(type(index_list)) # check the type after we find something we would like to append
        print('-----------') # break the text up
        if(len(list_ind) != 0):
            try:   
                for i in range(len(list_ind)):
                    print('loop i')
                    index_list.append(int(list_ind[i]))
            except AttributeError:
                print('the end is nigh') # I like Watchmen
                try:   
                    for i in range(len(list_ind)):
                        print('loop j')
                        print(type(index_list))
                        index_list.insert(int(list_ind[i]))
                except AttributeError:
                    print('the end') # break if error
                    break
print(index_list)

运行此程序后,我得到以下输出。 (我很抱歉这篇文章的长度,但我正在搜索的 df 有 1507524 行和 71 列。

<class 'list'>
col loop
------------
<class 'list'>
col loop
------------
<class 'list'>
col loop
------------
shape is greater than 1x1
<class 'list'>
-----------
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
loop i
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
<class 'numpy.ndarray'>
col loop
------------
shape is greater than 1x1
<class 'numpy.ndarray'>
-----------
loop i
the end is nigh
loop j
<class 'numpy.ndarray'>
dough
[  61708   99779  118192  118193  164900  164901  210027  210030  210031
  232259  255711  379029  379030  496978  497010  497011  578759  852625
  941357  941359  941363  941375 1029671 1136526 1212745 1315677 1328337
 1333935 1342118 1401022 1462777 1462778 1462779 1462781]

我已尝试解决此问题;但是,到目前为止,我还没有运气。任何可以帮助我解决这个问题的帮助将不胜感激。

【问题讨论】:

  • 对象不能改变类型。必须为 index_list 变量赋值,但它不在您发布的代码中。
  • 是否有理由在循环 j 中使用 index_list.insert 而在其他地方使用 append
  • @Barmar 这是文件中的唯一代码。我在 Anaconda 中使用 Jupiter Notebook。我已经重新启动了内核。我重写了每一行,以确保我没有错过一些愚蠢的东西。这就是为什么我不能围绕这个问题。当循环运行时,list 更改为numpy.ndarray,我终其一生都无法弄清楚原因。
  • @AJBiffl 我遇到了一个错误,所以我更改了代码并且它起作用了。我不明白为什么。
  • 改掉使用for index in range(len(list)):的习惯。使用for item in list:

标签: python pandas numpy loops numpy-ndarray


【解决方案1】:

看到你的照片后想通了。 pd.unique() 返回一个 numpy.ndarray。请改用list(set(index_list)) 或将其移出最外层的for 循环。

正如 AJ Biffle 指出的那样,您在 j 循环中使用 insert 而不是 append,这会导致错误,因为 insert 需要两个参数(插入对象的索引和对象) .您还应该尽量避免循环遍历数据帧。
我知道这不能回答问题(为什么会发生变化),但这应该得到所需的输出。很可能有更好的方法来做到这一点,但我不是数据框专家。

def check_for_keyword(x):
    keywords = []  # Add keywords to this list
    for keyword in keywords:
        if keyword.lower() in str(x).lower():  # Test this to see if x can be converted to string every time
            return True
    return False

data = data.applymap(lambda x: check_for_keyword(x)).any(axis=1)
row_indices = list(data.iloc[list(data)].index)

基本上applymap 遍历数据帧中的每个值,并将值更改为从传入函数返回的任何标量值。在这种情况下,如果在值中找到关键字,则返回True,否则返回Falseanyaxis=1 逐行检查是否有任何列值是 True,并返回布尔值的 1 列 Series。然后将这些值转换为list 并与iloc 一起使用以仅获取值为True 的行(具有包含关键字的列的行)。然后它抓取行的索引并将它们转换为列表。

另一个选项(因为列索引无关紧要)是使用open

keywords = []
row_indices = []
with open('./real_acct.txt') as f:
    for index, line in enumerate(f):
        for keyword in keywords:
            if keyword.lower() in line.lower():
                row_indices.append(index)
                break  # row contains at least one keyword, no need to check for more

【讨论】: