Python: модифицировать и редактировать фрейм данных внутри функции - PullRequest
0 голосов
/ 12 ноября 2019

У меня есть датафрейм, подобный следующему:

import pandas as pd

df = pd.DataFrame( {'Tester1': ['A','B','C','A','B','E','F','A','E','B','C','C'],
                    'Tester2':['D','A','E','A','B','F','F','A','B','B','A','C'],
                    'Day':['1','1','1','1','1','1','1','2','2','2','2','2'],
                    'Value':['-0.94','0.48','-0.79','-0.46','-1.02','0.31','-2.21','-2.1','-0.86','0.52','-0.23','0.71']})

Я хочу сделать следующие шаги:

  • a) Посмотрите на данные по дням. Например, сначала посмотрите на Day == 1
  • b) Сортируйте подмножество данных в порядке убывания Value
  • c) Возьмите пару Tester с наибольшим значением и добавьте ее ксписок и сохранить для будущего использования (обратите внимание, что пары тестеров могут быть одинаковыми или разными. Например, Тестер A и Тестер B или Тестер A и Тестер A.
  • d) Удалите все данные из подмножества, которое содержит либо (Спасибо @smci) Тестер 1 или Тестер 2 с наибольшим значением.

Повторите шаги с), d) до всех наблюдений для конкретногодень законченПовторяйте до тех пор, пока не будут выполнены все дни в наборе данных.

Мой текущий код:

day_list=list(set(d2['Day']))
data_list=[]
for day in day_list:

    # Creating subset of the data for days in the day_list - (Step a)

    data_per_day=d2[d2['Day']==day]
    for i in range(len(data_per_day)):

       # Sorting the data in descending order by value 

        sorted_data_per_day=data_per_day.sort_values('Value',ascending=False)

       # Taking the top observation and appending it to  data list - (Step b & c)

        zz=sorted_data_per_day.iloc[0,:].to_frame().T
        data_list.append(zz)

       # Creating a list of testers in the data which was stored - (Step d)

        tester_list1=(zz['Tester1'].iloc[0],zz['Tester2'].iloc[0])
        tester_list=list(set(tester_list1))

        # Removing all observations which contain Tester 1 or Tester 2 - (Step d contd.)

        sorted_data_per_day1=sorted_data_per_day[~sorted_data_per_day['Tester1'].isin(tester_list)]
        sorted_data_per_day2=sorted_data_per_day1[~sorted_data_per_day1['Tester2'].isin(tester_list)]
        sorted_data_per_day=sorted_data_per_day2

data_list2=pd.concat(data_list,axis=0)

Пример вывода для Day == 1 следующий:

Дляшаг а) и б) - Подмножество полученных данных и значения отсортированы

enter image description here

Для шага c) Возьмите пару тестеров с наибольшим значением

enter image description here

Для шага d) Удалить все пары тестеров, содержащие либо A, либо B.

enter image description here

Повторите все вышеуказанные шаги с этим новым набором наблюдений.

Прямо сейчас, я получаю следующее:

enter image description here

У меня ощущение, что я допустил ошибку в этих двух шагах кода:

i) for i in range(len(data_per_day)) # Should I change this to a while loop?

ii) sorted_data_per_day=sorted_data_per_day2 # Really not sure why this list is not getting updated

Любая помощь будет оценена. Заранее спасибо.

Пожалуйста, дайте мне знать, если какая-либо часть не ясна здесь. Я обновлю их.

Редактировать:

Я также пробовал следующее, но вывод не меняется:

sorted_data_per_day = data_per_day.sort_values('Value',ascending=False)
    for i in range(len(sorted_data_per_day)):

Ответы [ 2 ]

1 голос
/ 12 ноября 2019

Вы можете выполнить все шаги a), b), c) с помощью простого groupby().apply(...), по крайней мере, для первого прохода:

df.groupby('Day').apply(lambda x: x.sort_values('Value', ascending=False).head(1))

       Tester1 Tester2 Day Value
Day                             
1   1        B       A   1  0.48
2   11       C       C   2  0.71

Мы можем просто выбрать нужные столбцы, отброситьиндекс и вернуть в виде списка / набора / все, что вы хотите;Вы можете изменить этот код:

df.groupby('Day').apply(lambda x: x.sort_values('Value', ascending=False).head(1)[['Tester1','Tester2']] )
       Tester1 Tester2
Day                   
1   1        B       A
2   11       C       C

Шаг d) был неоднозначным, но вы уточнили, что он уменьшен до "Удалить / игнорировать все остальные записи в этой группе дня, которые содержат EITHER Tester1 ИЛИ Tester2 из шага c) "

Самое простое - это, вероятно, сохранить set тестеров, инициализировать его для всех тестеров на этот день и удалить тестеров (set.discard()), когда мы увидим, что эти тестеры встречаются в записях с самым высоким значением,Когда у нас закончились записи или тестеры, обработка в этот день заканчивается.

Также, когда вы говорите: «[Удалить] пару тестеров с самым высоким значением и добавить ее в список и сохранить для будущего использования»Как правило, нам не нужно удалять и добавлять подобные вещи из сгруппированных фреймов данных, мы можем просто опустить отсортированный список значений и исключить тестеры, которые мы уже видели, и мы можем установить некоторый целочисленный / логический флаг в дополнительном столбце. сказать, какие строки использует наш алгоритм. (Вы хотите сохранить только тестеры или всю строку, включая значение?)

Например, вот код, который получает тестер (ы) из верхней записи в каждой группе Day, каксписок:

>>> df.groupby('Day').apply(lambda grp: grp.sort_values('Value', ascending=False) [['Tester1','Tester2']].iloc[0].tolist() )
Day
1    [B, A]
2    [C, C]

В любом случае, вы можете адаптировать это, вы захотите написать некоторую итеративную функцию, которая входит в ваш вызов apply() для группы, которая возвращает, например, некоторый выходной кадр данных, например, с одним дополнительным столбцомKeep или что угодно.

0 голосов
/ 12 ноября 2019

Просто оставив это здесь на всякий случай, если кто-то еще столкнется с подобной проблемой в будущемПомогло изменение цикла for на цикл while.

#Incorrect code
for i in range(len(data_per_day)):

###########################    
#Correct code
###########################
while len(sorted_data_per_day)>0:

Вывод, который я получаю сейчас, показан ниже, и это именно то, что я искал.

enter image description here

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