Подсчет частоты изменения внутри переменной

#python #dataframe

Вопрос:

Я надеюсь определить частоту изменения «типа» (фиктивной переменной) по «идентификатору» в разных кварталах. Например, человек 1 переключил свой тип с » а » на «в», а затем обратно на » а » с 2019 по 2020 год. Итак, этот человек переключается дважды. Человек 2 переключился только один раз. Человек 3 никогда не переключается. Затем я надеюсь создать добавленную колонку под названием «частота», чтобы записать количество изменений по кварталам. В столбце частота у человека 1 должно быть 2, у человека 2-1, а у человека 3-0.

Я совсем новичок в python и сейчас у меня нет никакого существующего кода. Спасибо вам за вашу помощь!

год четверть Тип удостоверение личности
2020 q1 a 1
2020 q2 b 1
2019 q1 a 1
2019 q1 a 2
2019 q4 b 2
2019 q1 a 3
2019 q4 a 3

Ответ №1:

Что ж, мне удалось сделать то, о чем меня просили. Вроде того. Я согласен, что код можно еще больше упростить, чтобы сделать его более простым, но на данный момент я сделал все, что мог. Итак, в принципе, то, что я сделал, это сначала осмыслил все доступные данные. Сначала я освободил место для 8 кварталов в период с 2019 по 2020 год, но, поскольку данные были только для некоторых из них, я отказался от этой идеи.

Поэтому сначала я создал пустой список l с 7 пустыми списками внутри него для хранения данных:

 l = [] d = [[],[],[]] for i in range(7):  l.append(d)  

Что дало мне:

 [[[], [], []],  [[], [], []],  [[], [], []],  [[], [], []],  [[], [], []],  [[], [], []],  [[], [], []]]  

Кроме того, наличие или отсутствие года и кварталов не имеет значения для расчета частоты для каждого человека, поскольку только тип и идентификатор лица вносят вклад в этот расчет. Но они могут понадобиться позже, поэтому, помня об этом, я все еще использовал их. Но, как я уже упоминал, не видя никакой пользы, я применил другой подход к их хранению, то есть я обозначил 2019 год как 1, потому что это 1-й год и кварталы как 1,2,3,4 и, следовательно, 2020 год как 2. Например, первые данные : В 2020 году за квартал 4 человека 1 использовал a. Я сохранил его в списке как:

 l[0] = [21,'a',1 ]  

Где 21 относится к 2: 2020, 2: квартал 1, » а » хорошо относится к переменной а и 1 к человеку. На самом деле все очень просто.

Аналогично, я повторил то же самое для остальных, чтобы получить:

 l[0] = [21,'a',1 ] l[1] = [21,'b',1 ] l[2] = [11,'a',1 ] l[3] = [11,'a',2 ] l[4] = [11,'b',2 ] l[5] = [11,'a',3 ] l[6] = [11,'a',3 ]  

Теперь я сохранил их в списке l, и это выглядело так:

 l =  [[21, 'a', 1],  [21, 'b', 1],  [11, 'a', 1],  [11, 'a', 2],  [11, 'b', 2],  [11, 'a', 3],  [11, 'a', 3]]  

Наконец, последний шаг-составление списка частот с именем f, сокращенно от частоты. Для этого я составил список из 3 списков, относящихся к каждому из 3 человек. Внутренний список состоит из двух элементов: первый-это подсчет того, насколько изменился каждый человек, а второй-для текущего типа человека. Теперь, чтобы упростить его вычисление, я дал каждому -1 в качестве первого элемента и тип » c » в качестве второго элемента:

 f = [[-1,'c'],[-1,'c'],[-1,'c']]  

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

Теперь нужно рассчитать частоту и тем самым решить эту проблему. Это самая простая часть, в списке f индекс 0 для человека 1, 1 для 2 и 2 для 3. Кроме того, в списке l, в каждом внутреннем цикле, третьим элементом является сам человек. Хорошо, и что? Ну, если мы обратимся к этому третьему элементу и вычтем из него 1, мы в основном получим индекс для этого человека в списке частот. Я имею в виду, что l[0] = [21,'a',1 ] , значит, l[0][2] = 1 . И если я вычту из этого 1, мы получим 0, что является индексом для первого лица в таблице частот. Теперь мы делаем следующее: перебираем список l и сначала проверяем, совпадает ли тип человека в таблице частот с типом в списке, если да, то мы переходим к следующему, но если нет, мы увеличиваем первый элемент на 1, так как частота увеличилась, и мы обновляем тип второго элемента.

И это все:

 for i in range(7):  pid = l[i][2]   if f[pid-1][1] != l[i][1]:  f[pid-1][1] = l[i][1]  f[pid-1][0] = f[pid-1][0]   1  

И после запуска всего кода, который:

 l = [] d = [[],[],[]] for i in range(7):  l.append(d) l[0] = [21,'a',1 ] l[1] = [21,'b',1 ] l[2] = [11,'a',1 ] l[3] = [11,'a',2 ] l[4] = [11,'b',2 ] l[5] = [11,'a',3 ] l[6] = [11,'a',3 ] f = [[-1,'c'],[-1,'c'],[-1,'c']] for i in range(7):  pid = l[i][2]   if f[pid-1][1] != l[i][1]:  f[pid-1][1] = l[i][1]  f[pid-1][0] = f[pid-1][0]   1 for i in f:  print(f"The person {i[1]} has changed his type {i[0]} times.")  

Мы наконец-то получаем :

 The person a has changed his type 2 times. The person b has changed his type 1 times. The person a has changed his type 0 times.  

Ответ №2:

Вы пометили свой вопрос dataframe : Вы имеете в виду фрейм данных Pandas? Если да, то:

Ваш фрейм данных:

 df =   year quarter type person id 0 2020 q1 a 1 1 2020 q2 b 1 2 2019 q1 a 1 3 2019 q1 a 2 4 2019 q4 b 2 5 2019 q1 a 3 6 2019 q4 a 3  

Результат для

 df_freq = (  df.sort_values(["person id", "year", "quarter"])  .groupby("person id", as_index=False).type  .apply(lambda col: (col != col.shift()).sum() - 1)  .rename(columns={"type": "frequency"}) )  

является

 person id frequency 0 1 1 1 2 1 2 3 0  

Но я не понимаю, почему «у человека 1 должно быть 2»? Если вы посмотрите на хронологически упорядоченный (по person id ) фрейм данных

 year quarter type person id 0 2019 q1 a 1 1 2020 q1 a 1 2 2020 q2 b 1 3 2019 q1 a 2 4 2019 q4 b 2 5 2019 q1 a 3 6 2019 q4 a 3  

есть только 1 изменение?

Если вы не разберетесь

 df_freq = (  df.groupby("person id", as_index=False).type  .apply(lambda col: (col != col.shift()).sum() - 1)  .rename(columns={"type": "frequency"}) )  

в результате получается

 person id frequency 0 1 2 1 2 1 2 3 0