Комплексная фильтрация DataFrame

Я только начал работать с Pandas, и я пытаюсь понять, является ли это подходящим инструментом для моей проблемы.

У меня есть набор данных:

date, sourceid, destid, h1..h12 

Меня в основном интересует сумма каждого столбца H1..H12, но мне нужно исключить несколько диапазонов из набора данных.

Примерами могут служить:

исключить H4, H5, H6 данные, где исходный = 4944 и исключить H8, H9-H12, где пункт назначения = 481981 и …

… это может продолжаться для многих многих фильтров, поскольку мы постоянно удаляем данные, чтобы приблизиться к нашей окончательной модели.

Я думаю, что я видел в решении, что я мог бы создать список фильтров, которые хотел бы, а затем создать функцию для тестирования, но я не нашел хороший пример для работы.

Моя первоначальная мысль заключалась в том, чтобы создать копию df и просто удалить данные, которые нам не нужны, и если нам это нужно – мы могли бы просто скопировать их обратно из источника df, но это похоже на неправильную дорогу.

С помощью масок вам не нужно удалять данные из фреймворка данных. Например:

 mask1 = df.sourceid == 4944 var1 = df[mask1]['H4','H5','H6'].sum() 

Или прямо:

 var1 = df[df.sourceid == 4944]['H4','H5','H6'].sum() 

В случае нескольких фильтров вы можете комбинировать логические маски с булевыми операторами:

 totmask = mask1 & mask2 

вы можете использовать DataFrame.ix[] для установки данных в нули.

Сначала создайте фиктивный DataFrame:

 N = 10000 df = pd.DataFrame(np.random.rand(N, 12), columns=["h%d" % i for i in range(1, 13)], index=["row%d" % i for i in range(1, N+1)]) df["sourceid"] = np.random.randint(0, 50, N) df["destid"] = np.random.randint(0, 50, N) 

Затем для каждого из ваших фильтров вы можете позвонить:

 df.ix[df.sourceid == 10, "h4":"h6"] = 0 

так как у вас есть 600k строк, создайте массив масок по df.sourceid == 10 возможно, медленный. Вы можете создавать объекты Series, которые отображают значение в индекс DataFrame:

 sourceid = pd.Series(df.index.values, index=df["sourceid"].values).sort_index() destid = pd.Series(df.index.values, index=df["destid"].values).sort_index() 

а затем исключить h4, h5, h6, где sourceid == 10:

 df.ix[sourceid[10], "h4":"h6"] = 0 

найти идентификаторы строк, где sourceid == 10 и destid == 20:

 np.intersect1d(sourceid[10].values, destid[20].values, assume_unique=True) 

найти идентификаторы строк, где 10 <= sourceid <= 12 и 3 <= destid <= 5:

 np.intersect1d(sourceid.ix[10:12].values, destid.ix[3:5].values, assume_unique=True) 

sourceid и destid – это серии с дублируемыми значениями индекса, когда значения индекса в порядке, Pandas использует поиск, отсортированный для поиска индекса. это O (log N), быстрее создавать массивы масок, которые являются O (N).