Оптимизация кода - сравнение двух столбцов даты и времени по месяцам и создание нового столбца слишком медленно - PullRequest
1 голос
/ 07 октября 2019

Я пытаюсь создать новый столбец в кадре данных Pandas. Если два других столбца даты в моем фрейме данных имеют один и тот же месяц, тогда этот новый столбец должен иметь значение 1, в противном случае - 0. Кроме того, мне нужно проверить, совпадают ли идентификаторы с моим другим списком идентификаторов, который я ранее сохранял в другом месте. и пометьте их только 1. У меня есть некоторый код, но он бесполезен, так как я имею дело с почти миллиардом строк.

my_list_of_ids = df[df.bool_column == 1].id.values

def my_func(date1, date2):
    for id_ in df.id:
        if id_ in my_list_of_ids:
            if date1.month == date2.month:
                my_var = 1
            else:
                my_var = 0
        else:
            my_var = 0
    return my_var

df["new_column"] = df.progress_apply(lambda x: my_func(x['date1'], x['date2']), axis=1)

Ждали 30 минут и все еще 0%. Любая помощь приветствуется.

ОБНОВЛЕНИЕ (добавление примера):

id   |    date1   |    date2     | bool_column |  new_column |
id1    2019-02-13    2019-04-11     1                  0
id1    2019-03-15    2019-04-11     0                  0
id1    2019-04-23    2019-04-11     0                  1 
id2    2019-08-22    2019-08-11     1                  1
id2      ....
id3    2019-09-01    2019-09-30     1                  1
.
.
.

Что мне нужно сделать, это сохранить идентификаторы, которые равны 1 в моем bool_column, затем я перебираю всеидентификаторы в моем dataframe и проверка, если они находятся в ранее созданном списке (= 1). Затем я хочу сравнить месяц и год столбцов date1 и date2 и, если они одинаковы, создать new_column со значением 1, где они мах, в противном случае - 0.

Ответы [ 2 ]

1 голос
/ 07 октября 2019

Лучший способ справиться с соответствием месяца - использовать векторизацию в пандах и сделать следующее:

new_column = (df.date1.dt.month == df.date2.dt.month).astype(int)

То есть избегать использования apply() вместо DataFrame (что, вероятно, будет итеративным) и воспользоваться преимуществом базовой numpy векторизации. Ворота к такой функциональности почти всегда находятся в семействах Series функций и свойств, таких как семейство dt для дат, семейство str для строк и т. Д.

К счастью, у вас есть предварительноВычислили членство id_list в вашем bool_column, поэтому, чтобы добавить членство в качестве критерия, просто сделайте следующее:

new_column = ((df.date1.dt.month == df.date2.dt.month) & df.bool_column).astype(int)

Еще раз, & из двух Series использует векторизацию. Вы остаетесь в логическом пространстве до конца, а затем преобразуетесь в int с astype(int). Анализируя ваш код, мне приходит в голову, что итеративная проверка вашего id_list может быть настоящим ударом по производительности, даже больше, чем DataFrame.apply(). Что бы вы ни делали, любой ценой избегайте повторения вашего id_list в каждой строке, поскольку у вас уже есть вектор, обозначающий членство в ваших bool_column.

Кстати, я считаю, что в ваших примерах данных есть небольшая ошибка,Значение new_column для вашей третьей строки должно быть 0, поскольку ваше значение bool_column равно 0.

1 голос
/ 07 октября 2019

Панды способ сделать это:

mask = ((df['date1'].month == df['date2'].month) & (df['id'].isin(my_list_of_ids)))
df['new_column'] = mask.replace({False: 0, True: 1})

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...