【问题标题】:Create a list based on nested For loops基于嵌套的 For 循环创建列表
【发布时间】:2017-08-24 16:03:47
【问题描述】:

假设我正在使用不允许 pip 或 pandas 并且必须使用 Python 2.7 的客户端计算机。二进制文件和转换成 exe 是不允许的。我正在阅读 CSV,其中列标题为 numpy 的名称。

在我的数据集中,我试图生成一个订单列表,这些订单适用于设施、目的地、项目编号和其他因素的独特组合,其中 p 是读取的 csv 数据集。

CSV starting out

What it would look like if I did this in Excel. Order 字段中的值是我希望在名为 my_orders 的变量中作为列表的值。

我当前的代码如下:

progs = np.unique(p['Program'])
facil = np.unique(p['Facility'])
dest = np.unique(p['Destination']) 
reqs = np.unique(p['Requested'])
prods = np.unique(p['Produced'])
tier1 = np.unique(p['Tier1'])
tier2 = np.unique(p['Tier2'])

接着是下面的方法,最初是用 pandas 和 Python3 编写的,直到发现只有 2.7 和 numpy 可用:

for a in range(len(progs)):
    print("on Program ",a)
    ProgChild = {"name":progs[a], 'children':[]}
    for r in range(len(reqs)):
        reqChild = {"name":reqs[r], 'children':[]}
        for s in range(len(prods)):
            prodChild = {'name':prods[s], "children":[]}
            for g in range(len(progs)):
                programChild = {'name':progs[g], "children":[]}
                for i in range(len(facil)):
                    FacilChild={"name":facil[i], "children":[]}
                    for c in range(len(tier1)):
                        Tier1Child={"name":tier1[c], "children":[]}
                        for d in range(len(tier2)):
                            # here's where I'm in trouble:
                            Order_Cond = np.array[[progs[a]& reqs[r]&
                                prods[s]&progs[g]& facil[i]& tier1[c]]
                            my_orders = np.where(p['Orders'], Order_cond)
                            print my_orders
                            # do other things

如您所见,最初的意图是使用 For 循环来设置一个例程,该例程仅返回来自设施、目的地、程序等的唯一组合的订单列表。Order_cond 变量显然有错误的语法.

如果这是在 SQL 中,我只会说“从 My_Data 中选择订单,其中 progs=a & reqs=r;”等等。

我也考虑过列表推导,但它也不起作用:

list(x for p['Orders'] in p if p['Orders'] in Order_cond)

同样,目标是创建一个订单列表并将其存储在 my_orders 中,然后我将其用于其他功能。

【问题讨论】:

  • 您能否给出一个实际的 CSV 示例,而不仅仅是一个 png?
  • 对于这种访问,在 SQL 中加载这些数据可能更简单。遍历数组的行(元素)并将它们写入数据库应该不难。在stackoverflow.com/a/35184195/901925 中,我说明了从 sql 加载结构化数组。另一个方向应该很容易。或在这里:stackoverflow.com/questions/32770340/…
  • 顺便说一句,这不是列表推导式,而是您将其具体化为列表的生成器表达式。不过,您应该只使用列表理解。

标签: python python-2.7 numpy


【解决方案1】:

我没有遵循您的整个嵌套 if 代码,但这是一种识别结构化数组中满足特定条件的记录的方法

制作一个包含 3 个字段的示例数组:

In [447]: dt = np.dtype('S10,S10,int')
In [448]: data = np.ones((10,),dt)
In [451]: data['f0']='one two three four five six seven eight nine ten'.split()
In [452]: data['f1']='a b c a b c a b c a'.split()
In [453]: data['f2']=np.arange(10)
In [454]: data
Out[454]: 
array([(b'one', b'a', 0), (b'two', b'b', 1), (b'three', b'c', 2),
       (b'four', b'a', 3), (b'five', b'b', 4), (b'six', b'c', 5),
       (b'seven', b'a', 6), (b'eight', b'b', 7), (b'nine', b'c', 8),
       (b'ten', b'a', 9)], 
      dtype=[('f0', 'S10'), ('f1', 'S10'), ('f2', '<i4')])

测试一个字段:

In [461]: cond = data['f0']==b'three'
In [462]: cond
Out[462]: array([False, False,  True, False, False, False, False, False, False, False], dtype=bool)

另一个有多个匹配项的字段:

In [463]: cond = data['f1']==b'c'
In [464]: cond
Out[464]: array([False, False,  True, False, False,  True, False, False,  True, False], dtype=bool)

结合几个现场测试:

In [465]: cond = (data['f1']==b'c') & (data['f0']==b'three') & (data['f2']==2)
In [466]: cond
Out[466]: array([False, False,  True, False, False, False, False, False, False, False], dtype=bool)
In [467]: data[cond]
Out[467]: 
array([(b'three', b'c', 2)], 
      dtype=[('f0', 'S10'), ('f1', 'S10'), ('f2', '<i4')])

还是走sql路线:

In [468]: import sqlite3
In [469]: conn=sqlite3.connect(':memory:')
In [470]: cur = conn.cursor()
In [471]: cur.execute('''CREATE TABLE array (f0 str, f1 str, f2 int)''')
Out[471]: <sqlite3.Cursor at 0xaa0a38a0>
In [472]: cur.executemany("INSERT INTO array VALUES (?,?,?)",data)

data 的元素看起来就像一个元组;所以插入是微不足道的。

Out[472]: <sqlite3.Cursor at 0xaa0a38a0>
In [473]: cur.execute('select * from array')
Out[473]: <sqlite3.Cursor at 0xaa0a38a0>
In [474]: cur.fetchall()
Out[474]: 
[(b'one', b'a', b'\x00\x00\x00\x00'),
 (b'two', b'b', b'\x01\x00\x00\x00'),
 (b'three', b'c', b'\x02\x00\x00\x00'),
 ...
 (b'ten', b'a', b'\t\x00\x00\x00')]
In [486]: cur.execute('select * from array where f0==(?)',(b"four",))
Out[486]: <sqlite3.Cursor at 0xaa0a38a0>
In [487]: cur.fetchall()
    Out[487]: [(b'four', b'a', b'\x03\x00\x00\x00')]
In [488]: cur.execute('select * from array where f0==(?) or f1==(?)',(b"four",b"c"))
Out[488]: <sqlite3.Cursor at 0xaa0a38a0>
In [489]: cur.fetchall()
Out[489]: 
[(b'three', b'c', b'\x02\x00\x00\x00'),
 (b'four', b'a', b'\x03\x00\x00\x00'),
 (b'six', b'c', b'\x05\x00\x00\x00'),
 (b'nine', b'c', b'\x08\x00\x00\x00')]

这个例子需要更简洁,但它给出了可能的粗略概念。

【讨论】:

    【解决方案2】:

    所以您想从 csv 文件中选择与某些列的某些值相对应的行?在 python 2.7 中不少于?好的,这对于 2.7 来说并不难

    您会发现csv.DictReader 最容易做到这一点,它将您的 csv 文件作为字典行读取,其中的键对应于每行的列标签。然后,给定一个您想要选择的键值对字典,下面的代码返回一个符合您想要的字典数组。如果你想去掉键值对,只拥有值数组this is trivially implemented。由于您可以将您的 csv 文件转换为字典列表,因此只需 selecting a dictionary from an array with certain values for keys

    import csv
    
    def dict_has_key_values(dict, dict_key_values):
        for key in dict_key_values:
            if not(key in dict and dict[key] == dict_key_values[key]):
               return False
        return True
    
    def select_from_dict(csv_dict_reader, dict_key_values):
        list_of_dict = []
        for row_dict in csv_dict_reader:
            if dict_has_key_values(dict, dict_key_values):
                 list_of_dict.append(dict)
        return list_of_dict
    
    
    with open('yourfile.csv') as csvfile:
        selected_key_values = {...}
        reader = csv.DictReader(csvfile)
        selected_rows = select_from_dict(reader, selected_key_values)
    

    selected_rows 现在应该有每一行

    A:至少有selected_key_values中的每一个key,并且

    B:与这些键关联的值是相同的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-14
      相关资源
      最近更新 更多