#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