【问题标题】:How can I iterate until all entries are in a given column?如何迭代直到所有条目都在给定列中?
【发布时间】:2021-04-29 04:52:51
【问题描述】:

我正在尝试将 while 语句应用于我的代码,以便运行它,直到下面列表中的所有元素(在 Check 列中)都在 Source 列中。

到目前为止,我的代码是这样的:

while set_condition: # to set the condition
     newCol = pd.Series(list(set(df['Check']) - set(df['Source']))) # this check for elements which are not currently included in the column Source
     newList1 = newCol.apply(lambda x: my_function(x)) # this function should generate the lists n Check -> this explains why I need to create a while statement
     df = df.append(pd.DataFrame(dict('Source'=newCol, 'Check'=newList1)), ignore_index=True) # append the results in the new column
     df = df.explode('Check')

我会给你一个例子来说明这个过程以及my_function是如何工作的:假设我有我的初始数据集

Source       Check
mouse   [dog, horse, cat]   
horse   [mouse, elephant]   
tiger   []  
elephant [horse, bird]

在分解Check 列并将结果附加到Source 之后,我将拥有

Source       Check
mouse   [dog, horse, cat]   
horse   [mouse, elephant]   
tiger   []  
elephant [horse, bird]
dog     [] # this will be filled in after applying the function
cat     [] # this will be filled in after applying the function
bird    [] # this will be filled in after applying the function

在应用函数之前,列表中的每个元素都应该添加到 Source 列中。 当我应用这个函数时,我填充了其他元素的列表;所以,例如我可以有

Source       Check
mouse   [dog, horse, cat]   
horse   [mouse, elephant]   
tiger   []  
elephant [horse, bird]
dog     [mouse, fish]  # they are filled in
cat     [mouse]
bird    [elephant, penguin]
fish    [dog]

由于fishpenguin 不在Source 中,我需要再次运行代码以获得预期的输出(列表中的所有元素都已经在Source 列中):

Source       Check
mouse   [dog, horse, cat]   
horse   [mouse, elephant]   
tiger   []  
elephant [horse, bird]
dog     [mouse, fish] 
cat     [mouse]
bird    [elephant, penguin]
fish    [dog]
penguin [bird]

因为dogbird 都已经在Source 中,所以我不需要再次应用该函数,因为所有列表都填充了源列中已经存在的元素。代码可以停止运行。

我想做的是在列表中的所有元素都在列 Source 中并应用该函数填充所有列表时停止循环/循环。

感谢您提供的所有帮助。

【问题讨论】:

  • 我不明白你的问题。在“应用功能后,我会有例子”这一步中,企鹅来自哪里?为什么狗与老鼠和鱼有关?不知道自己想做什么就很难回答。
  • @ApplePie 这很简单,但我同意我不是很清楚;)我在检查列中有列表。我想在 Source 列中包含所有元素(没有重复项)。每当我在 Source 中有新元素时,my_function 都会生成它们在 Check 中的相关列表。我想运行(然后停止)该过程,直到所有列表都包含已经在源中的元素。我试图在帖子中解释得更好
  • 如果您可以提供最小的可重现输入,这将有所帮助。谢谢。
  • 嗨,Akshay,不幸的是,我不知道如何总结从源列表中随机生成元素的函数,包括新元素。您可以考虑从 1 到 100 的数字(假设 Source 列中只有奇数)以及在 Check 列的列表中随机生成奇数和偶数的函数。由于在 Source 列中只有奇数(假设我们有 5 行)并且第一个列表包含奇数和偶数,因此我需要在 Source 列中添加偶数。他们还没有任何列表,因为我必须将函数重新应用到他们每个人。
  • 一旦将函数应用到包括偶数在内的每一行,我就会有奇数和/或偶数的新列表。需要添加尚未包含在“源”列中的所有数字。然后我应该重新应用该函数来生成新列表。当列表中的所有数字都正确添加到源列中并且全部带有列表时,我将需要停止该过程。我想提供更多帮助,但我只能解释函数是如何工作的,以便使循环应该做的事情更简单。对于那个很抱歉。很高兴回答您可能遇到的所有问题

标签: python pandas while-loop


【解决方案1】:

如果您重复循环直到没有更多行要添加到 DataFrame,这与说df['Check'] 的所有元素都在df['Source'] 中找到是一样的。无论如何,您必须计算每个循环,那么为什么不使用它来跳出循环呢?

while True: # loop forever!
     diff = set(df['Check']) - set(df['Source'])
     if len(diff) == 0:
         break # done!
     newCol = pd.Series(list(diff))
     newList1 = newCol.apply(lambda x: my_function(x))
     df = df.append(pd.DataFrame(dict('Source'=newCol, 'Check'=newList1)), ignore_index=True)
     df = df.explode('Check') # NOTE: I will use this to my advantage in the next suggested solution

因为continually appending to a DataFrame is taxing on memory,您可能需要考虑先构建列,然后在循环之外一次构建DataFrame。 df['Check'] 无论如何都会爆炸,所以从爆炸开始并建立在这些列表上:

df = df.explode('Check')
check = df['Check']                # Append to this list as we iterate
source = df['Source']              # Append to this list as we iterate
unique_source = set(source)
diff = set(check) - unique_source  # Iterate until this is empty
while len(diff) > 0:
    new_check = [my_function(x) for x in diff] # a list of lists
    check.append(new_check)    # Add the list of lists as-is, but explode later
    source.append(diff)        # Keep track of the new sources for the DataFrame...
    unique_source.update(diff) # and keep track of the unique sources for efficiency
    flat_check = set(x for sublist in new_check for x in sublist)
    diff = flat_check - unique_source  # We only have to check the new elements!

df = pd.DataFrame({"Check": check, "Source": source}).explode("Check") # build the entire DataFrame at once

有很多方法可以使用这个结构来获得你想要的 DataFrame 的结构。例如,如果您不想爆炸df['Check'],只需保留本示例开头的df 的原始版本,并将新数据附加到该版本:

new_df = df.explode('Check')
unique_source = set(new_df['Source'])
diff = set(new_df['Check']) - unique_source
source = [] # append to empty lists
check = []  # append to empty lists
while len(diff) > 0:
    # ...

df = pd.append([df, pd.DataFrame({"Check": check, "Source": source})]) # keep the unexploded columns

【讨论】:

    【解决方案2】:

    据我大致了解,我想说您可以使用 pandas .unique() 对列表中的每个唯一值进行排序,然后使用 for 或 while 循环检查源列中是否存在新的唯一值。

    【讨论】:

    • 嗨 samar2170。我在编写循环和检查语句时遇到困难(这就是我问的原因。我可以如何设置问题和步骤,但我不知道如何正确使用 while(我认为它会是更合适)并检查两列的值以停止函数并获得最终结果;)
    【解决方案3】:

    我假设数据被自动附加到数组中,你可以使用:

    x = df['columnName'].values[-1]
    for i in df['source']:
        if i == x:
            return(x)
    

    【讨论】:

      【解决方案4】:

      您本质上想要的是在newCol 为空时停止。另一种表述方式是set(df['Check'])set(df['Source'] 的子集。所以你想要:

      while ( set(df['Check']).issubset(set(df['Source']) == False ):
      

      【讨论】:

        猜你喜欢
        • 2013-02-22
        • 2015-07-18
        • 1970-01-01
        • 2014-12-29
        • 2021-05-02
        • 2020-06-16
        • 1970-01-01
        • 2019-01-24
        • 1970-01-01
        相关资源
        最近更新 更多