Фильтрация по группам pandas по значению столбца (тип данных строки) - PullRequest
1 голос
/ 30 января 2020

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

# ID   |  functionality   |   v_region_score   |   constant_region 
# -----------------------------------------------------------------
# 123  |  productive      |      820           |      NaN
#      |  unknown         |      720           |      NaN
#      |  unknown         |      720           |      IgM
# 456  |  unknown         |      690           |      NaN
#      |  unknown         |      670           |      NaN
# 789  |  productive      |      780           |      IgM
#      |  productive      |      780           |      NaN

(Правка) Вот код для примера dataframe:

df1 = pd.DataFrame([
    [789, "productive", 780, "IgM"],
    [123, "unknown", 720, np.nan],
    [123, "unknown", 720, "IgM"],
    [789, "productive", 780, np.nan],
    [123, "productive", 820, np.nan],
    [456, "unknown", 690, np.nan],
    [456, "unknown", 670, np.nan]], 
    columns=["ID", "functionality", "v_region_score", "constant_region"])

И это будет окончательный вывод с выбранными правильными строками:

df2 = pd.DataFrame([
    [789, "productive", 780, "IgM"],
    [123, "productive", 820, np.nan],
    [456, "unknown", 690, np.nan]], 
    columns=["ID", "functionality", "v_region_score", "constant_region"])

Поэтому после группировки для каждой группы, если она имеет «производительное» значение в функциональности, я хочу сохранить эту строку, если она «неизвестна», я беру самый высокий v_region_score, и если есть несколько «производительных» значений, я беру тот, который имеет некоторое значение в своем constant_region.

Я пробовал несколько способов доступа к этим значениям:

id, frame = next(iter(df_grouped))

if frame["functionality"].equals("productive"):
    # do something

Просмотр только одной группы:

x = df_grouped.get_group("1:1101:10897:22442")

for index, value in x["functionality"].items():
    print(value)

# returns the correct value and type "str"

Даже помещение каждой группы в список:

new_groups = []

for id, frame in df_grouped:
    new_groups.append(frame)

# access a specific index returns a dataframe
new_groups[30]

Ошибка, которую я получаю со всеми из них: «Значение истинности Серии неоднозначно», и теперь я понимаю, почему это не работает, но я не могу использовать a.any(), a.all() или a.bool() из-за сложности условного выражения.

Можно ли каким-либо образом выбрать определенную строку c в каждой группе на основе значений ее столбцов? Извините за такой сложный вопрос и заранее спасибо! :)

1 Ответ

2 голосов
/ 30 января 2020

Вы можете подойти к своей проблеме под другим углом:

  1. Сортировать значения на основе ваших критериев
  2. Группировать по ID
  3. Сохранить первый результат для сгруппированных ID

Например:

df1 = df1.sort_values(['ID','functionality','v_region_score','constant_region'], ascending=[True,True,False,True], na_position='last')

df1.groupby('ID').first().reset_index()

Out[0]:
    ID functionality  v_region_score constant_region
0  123    productive             820             IgM
1  456       unknown             690             NaN
2  789    productive             780             IgM

Кроме того, если вы хотите объединить значения из constant_region, когда это null, вы можете использовать fillna(method='ffill'), чтобы вы сохранить существующее значение:

## sorted here

df1['constant_region'] = df1.groupby('ID')['constant_region'].fillna(method='ffill')

df1
Out[1]: 
    ID functionality  v_region_score constant_region
4  123    productive             820             NaN
2  123       unknown             720             IgM
1  123       unknown             720             IgM
5  456       unknown             690             NaN
6  456       unknown             670             NaN
0  789    productive             780             IgM
3  789    productive             780             IgM

## Group by here
...