使用 DataFrame 时迭代一对行

Iterating with a pair of rows when working with DataFrame

为了遍历 DataFrame 的每一行,我使用 .iterrows():

list_soccer = pd.DataFrame({
    'EventName': [obj_event.event.name for obj_event in matches],
    'IDEvent': [obj_event.event.id for obj_event in matches],
    'LocalEvent': [obj_event.event.venue for obj_event in matches],
    'CodeCountry': [obj_event.event.country_code for obj_event in matches],
    'TimeZone': [obj_event.event.time_zone for obj_event in matches],
    'OpenDate': [obj_event.event.open_date for obj_event in matches],
    'Total_Market': [obj_event.market_count for obj_event in matches],
    'Local_Date': [obj_evento.event.open_date.replace(tzinfo=datetime.timezone.utc).astimezone(tz=None) 
                            for obj_evento in matches]
    })

for_iterate = list_soccer.reset_index()
for_iterate = for_iterate[for_iterate['EventName'].str.contains(" v ")]
data_for_compare = (datetime.datetime.utcnow()).strftime("%Y-%m-%d %H:%M")
for_iterate = for_iterate[for_iterate['OpenDate'] >= data_for_compare]
    
for index, example_dataframe in for_iterate.iterrows():
    multiprocessing.Process(target=add_hour, args=(example_dataframe,))

因为我需要将这次迭代的速度加倍(同时调用两个 multiprocessing),所以我正在寻找一种同时使用两条线的方法。

如果它是一个常规列表(请注意我在下面给出这个例子只是为了演示我需要什么,我知道列表和数据框之间没有任何相似之处),我可以这样做:

a_list = ['a','b','c','d']
a_pairs = [a_list[i:i+2] for i in range(0, len(a_list)-1, 2)]
# a_pairs = [['a','b'],['c','d']]
for a, b in a_pairs:
    multiprocessing.Process(target=add_hour, args=(a,))
    multiprocessing.Process(target=add_hour, args=(b,))

我应该如何使用 DataFrame 同时处理两行?

在这个问题中,我找到了两个答案,但它们提供了在 DataFrame 中重复值的选项:

我无法创建的是一个模型,这样行就不会重复,例如,使用行 0 and 1 然后使用 2 and 3 然后使用 4 and 5,所以也许有人说这个问题重复了,但实际上我的需求不同,我无法根据需要将这些选项转换为一个选项。

您应该能够将 DataFrame 一分为二,使用与列表类似的索引。

然后,您可以一次遍历两者,这会按顺序一次给您两行(所以 0,1 然后 2,3 等)

df_a = for_iterate.iloc[::2] # Get all the even rows
df_b = for_iterate.iloc[1::2] # Get all the odd rows

for (_, example_dataframe_a), (_, example_dataframe_b) in zip(df_a.iterrows(), df_b.iterrows()):
    multiprocessing.Process(target=add_hour, args=(example_dataframe_a,))
    multiprocessing.Process(target=add_hour, args=(example_dataframe_b,))

(虽然我不清楚为什么你需要为数据帧的每一行生成一个进程,而不是两个进程,每个 for_iterate 的一半)。

或者:

您可以尝试使用 multiprocessing.Pool.map() 一次执行两个请求。与上面的方法不同,一个新的请求会在前一个请求完成后立即发出(因此它不会等待两个都完成后再分派下两个),并且只需要两个进程可能是 re-used:

from multiprocessing import Pool

def add_hour_wrapper(data):
  # iterrows returns two arguments, we only want one
  _, row = data
  return add_hour(row)

pool = Pool(2) # 2 processes

pool.map(add_hour, for_iterate.iterrows())