Есть ли какой-либо другой способ избежать дублирования результата путем зацикливания внутри циклического python (не groupby / transform)?

#python #pandas #indexing

#python #pandas #индексирование

Вопрос:

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

данные, как показано ниже:

 df = pd.DataFrame({'date' : ['16-04-2020', '20-04-2020', '16-04-2020', '16-04-2020', '20-04-2020', '20-04-2020', '16-04-2020'],
                    'item' : ['X-317', 'ry-186', 'opq-468','999-xq','789-44','154-abc','opq-468'],
                    'no': ['36','55','45','77','107','1149','456' ],
                    'result':['','','','','','','']})


df_list = pd.DataFrame({'date' : ['16-04-2020', '16-04-2020', '16-04-2020', '20-04-2020', '16-04-2020', '16-04-2020', '20-04-2020'],
                        'item' : ['opq-468', 'ry-186','789-44','154-abc', 'opq-468','opq-468','123-x'],
                        'complete': ['yes','no','on-going','yes','yes','yes','no' ],
                        'code':['alpha', 'vertical','horizon','grand','empire','jade','roms']})
 

я намереваюсь сопоставить date, complete = ‘yes’ и item в df такой же, как df_list, но если в результате есть что-то похожее, он продолжит поиск следующего, а затем, после этого, если индекс не равен None или -1, я бы использовал его в своем следующем определении

я пробовал ниже:

 for j in range(len(df)):
    def test():
        index=-1
        for i in range(len(df_list)):
            if ((df_list['date'][i] == df['date'][j] ) and (df_list['complete'][i] == 'yes') and (df_list['item'][i] == df['item'][j])):        
                index = i
        return index
    print(test())
      
    if test() != -1:
        .... (other def)

 

и мой результат для test() равен [-1 -1 5 -1 -1 3 5], где 5 повторяется

Ожидаемая печать (test ()) должна быть:

          date     item    no result   **test()**
0  16-04-2020    X-317    36           -1
1  20-04-2020   ry-186    55           -1
2  16-04-2020  opq-468    45            0
3  16-04-2020   999-xq    77           -1
4  20-04-2020   789-44   107           -1
5  20-04-2020  154-abc  1149            3
6  16-04-2020  opq-468   456            4
 

Ответ №1:

По моему опыту, более эффективно использовать методы pandas вместо циклов и индексов. Вы можете обойти эту проблему, используя pandas merge .

Ниже приведена реализация вашего намерения.

я намерен сопоставить date, complete = ‘yes’ и item в df такой же, как df_list

pandas doc pandas merge

 df = pd.DataFrame({'date' : ['16-04-2020', '20-04-2020', '16-04-2020', '16-04-2020', '20-04-2020', '20-04-2020', '16-04-2020'],
                     'item' : ['X-317', 'ry-186', 'opq-468','999-xq','789-44','154-abc','opq-468'],
                         'no': ['36','55','45','77','107','1149','456' ],
                          'result':['','','','','','','']})
     
   
df_list = pd.DataFrame({'date' : ['16-04-2020', '16-04-2020', '16-04-2020', '20-04-2020', '16-04-2020', '16-04-2020', '20-04-2020'],
                              'item' : ['opq-468', 'ry-186','789-44','154-abc', 'opq-468','opq-468','123-x'],
                             'complete': ['yes','no','on-going','yes','yes','yes','no' ],
                             'code':['alpha', 'vertical','horizon','grand','empire','jade','roms']})

res = df.merge(df_list, on=['date','item'], how='inner')

res[res['complete']=='yes']

Out[30]:

      date     item    no result complete    code
0  16-04-2020  opq-468    45             yes   alpha
1  16-04-2020  opq-468    45             yes  empire
2  16-04-2020  opq-468    45             yes    jade
3  16-04-2020  opq-468   456             yes   alpha
4  16-04-2020  opq-468   456             yes  empire
5  16-04-2020  opq-468   456             yes    jade
6  20-04-2020  154-abc  1149             yes   grand
 

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

1. метод слияния, похоже, не работает, поскольку мое реальное количество данных превышает тысячи, и я буду использовать больше критериев при сопоставлении. и результат не то, что я хочу, спасибо в любом случае

Ответ №2:

я нашел метод с использованием list и count, хочу узнать, есть ли другой метод, спасибо

 listrange = []
count = []
for j in range(len(df)):
    def test():
        index=-1
        for i in range(len(df_list)):
            if ((df_list['date'][i] == df['date'][j] ) and (df_list['complete'][i] == 'yes') and (df_list['item'][i] == df['item'][j]) and
                count.count(j) == listrange.count(i)):        
                listrange.append(i)
                count.append(j)
                index = i                              
        return index
    # print(test())
    if test() != -1:
        print(test())