Сдвиньте записи в фрейме данных Pandas с условиями

#python #pandas

Вопрос:

Я боролся с изменением позиции pandas record в зависимости от конкретных условий. Что я хочу сделать, так это переместить каждую строку, имеющую значение в столбце before_id(она включает строку), в следующее индексное место другой строки, значение которой в node_id(она включает строку) совпадает с ней. И мой код не сработал так, как я ожидал. Он не вернул никаких ошибок, но вообще не сортировал их.

Хотя я немного беспокоюсь о своем объяснении …. У вас есть какая-нибудь идея, как этого добиться ?? или это невозможно сделать у Панд ??

 client_data = """node_id,option,before_id
    1aa,A,
    8xyz,C,2aa
    2aa,A,1aa
    5mm,A,4bb
    4bb,C,8xyz
    6ccc,5mm,
    7,C,6ccc       
    """


df = pd.read_csv(io.StringIO(client_data), dtype='string', error_bad_lines=False)
    before = pd.notnull(df['before_id'])
    for ind,row in df.iterrows():
        if pd.notnull(row[2]):
            before_id = row[2]
            before_ind = df.index[df['node_id']==before_id]
            next_ind = before_ind   1
            row.reindex(index=next_ind)
        else:
            pass
 
 df

node_id,option,before_id
1aa,A,
8xyz,C,2aa
2aa,A,1aa
5mm,A,4bb
4bb,C,8xyz
6ccc,5mm,
7,C,6ccc


ideal output 

node_id,option,before_id
1aa,A,
2aa,A,1aa
8xyz,C,2aa
4bb,C,8xyz
5mm,A,4bb
6ccc,5mm,
7,C,6ccc
 

Комментарии:

1. Ваш пример сложен и неоднозначен. Не могли бы вы привести минимальный пример, содержащий только уникальные цифры или отдельные буквы, чтобы прояснить вашу логику? Например, как 5 изменяется значение второго ряда 2xxx ?

2. Как 5 меняется значение во втором ряду 2xxx , но 8 не меняется значение в третьем 1aa ?

3. Спасибо за комментарий , я написал это неправильно по ошибке . Я уже отредактировал df и удалил дубликаты. Все выглядит нормально ??

Ответ №1:

Похоже, вы пытаетесь решить проблему с графом поиска, ориентированным на глубину. Ниже приведено решение с использованием библиотеки графиков networkx.

 import pandas as pd
import io

x = '''node_id,option,before_id
1aa,A,
8xyz,C,2aa
2aa,A,1aa
5mm,A,4bb
4bb,C,8xyz
6ccc,5mm,
7,C,6ccc'''

df = pd.read_csv(io.StringIO(x))
print("Originaln",df)
print('--------------n')

import networkx as nx
G = nx.from_pandas_edgelist(df, 'before_id', 'node_id', 'option')
sortedNodes = [n[1] for n in list(nx.dfs_edges(G))]

df.node_id = df.node_id.astype('category')
df.node_id.cat.set_categories(sortedNodes, inplace=True)
df = df.sort_values(['node_id'])
print("Node-sortedn",df)
 

Выход:

 Original
   node_id option before_id
0     1aa      A       NaN
1    8xyz      C       2aa
2     2aa      A       1aa
3     5mm      A       4bb
4     4bb      C      8xyz
5    6ccc    5mm       NaN
6       7      C      6ccc
--------------

Node-sorted
   node_id option before_id
0     1aa      A       NaN
2     2aa      A       1aa
1    8xyz      C       2aa
4     4bb      C      8xyz
3     5mm      A       4bb
5    6ccc    5mm       NaN
6       7      C      6ccc
 

Комментарии:

1. Кроме того, python 3.9 имеет встроенную библиотеку graphlib, которая может предоставлять те же возможности, что и networkx. Вы можете проверить это по адресу: docs.python.org/3/library/graphlib.html

2. Огромное спасибо. Ваш код работает без каких-либо ошибок, но он возвращает результаты, отличные от ваших . Может быть , как вы сказали, это зависит от моей версии Python, 3.8. Я проверю документы.