У меня есть большой набор данных CSV файлов, состоящий из двух разных объектов: "object_a" и "object_b". Каждое из этих объектов также имеет числовое значение "галочка".
Type, Parent Name, Ticks
object_a, 4556421, 34
object_a, 4556421, 0
object_b, 4556421, 0
object_a, 3217863, 2
object_b, 3217863, 1
......
Каждый объект имеет значение "Родительское имя", поэтому в большинстве случаев один из каждого объекта будет иметь значение "Родительское имя", но это не всегда так.
У меня есть две цели с этим набором данных:
-
извлечь все object_a под родительским именем, где i) есть > 1 object_a и; ii) объект_a имеет 0 тиков, но у другого объекта object_a есть > 0 тиков. т.е. только с нулевыми тиками
-
извлечь все object_b под родительским именем, где i) существует >= 1 object_a и; ii) объект_b имеет 0 тиков, но object_a имеет > 0 тиков
Мой первый подход состоит в том, чтобы иметь две отдельные функции для обеих задач, читать CSV файлы (обычно размером 1,5 ГБ) в кусках и выводить извлеченные строки в другой CSV файл после группировки их в соответствии с родительским именем...
def objective_one(group_name, group_df):
group_df = group_df[group_df['Type'] == 'object_a']
if len(group_df) > 1:
zero_tick_object_a = group_df[group_df['Ticks'] == 0]
if len(zero_click_object_a) < len(group_df):
return zero_click_object_a
else:
return pd.DataFrame(columns=group_df.columns)
else:
return pd.DataFrame(columns=group_df.columns)
def objective_two(group_name, group_df):
object_a_in_group_df = group_df[group_df['Type'] == 'object_a']
object_b_has_no_clicks_in_group_df = group_df[(group_df['Type'] == 'object_b') & (group_df['Ticks'] == 0)]
if len(object_a_in_group_df) >= 1 and len(object_b_has_no_ticks_in_group_df) >= 1:
has_ticks_objects = objects_in_group_df[object_a_in_group_df['Ticks'] >= 1]
if len(has_ticks_object_a) > 0:
return object_B_has_no_ticks_in_group_df
else:
return pd.DataFrame(columns=group_df.columns)
else:
return pd.DataFrame(columns=group_df.columns)
Вот вызовы этих функций в основном методе:
for chunk in pd.read_csv(file, chunksize=500000):
#objective one
chunk_object_a = chunk.groupby(['Parent Name']).apply(lambda g: objective_one(g.name, g))
....
....
#objective two
chunk_object_b = chunk.groupby(['Parent Name']).apply(lambda g: objective_two(g.name, g))
# Затем запишите файлы данных, полученные методом применения, в файл csv
Проблема с этим подходом заключается в том, что, хотя он и дает мне вывод, который я хочу, он очень медленный в больших файлах в диапазоне 1 ГБ и выше. Другая проблема заключается в том, что чтение его в кусках из CSV может эффективно сократить некоторые группы пополам (то есть, имя родителя может быть разделено на один кусок, а следующий, что делает невозможным выделение неточного количества)
Есть ли способ оптимизировать это, чтобы сделать его быстрее, а также обойти мою проблему с блоком?