Условная итерация строки в Pandas для создания новой функции - PullRequest
0 голосов
/ 15 марта 2020

У меня есть данные, подобные этому примеру:

df11 = pd.DataFrame({'code': [33000000, 33230000, 33235600, 33235678, 17000000,17980000],
                 'Name': ['txt1','txt2','txt3','txt4','txt5','txt6'],
                'level': [1,2,3,4,3,4]})
print(df11)

Моя цель состоит в том, чтобы перебирать строки (в действительности около 100 000 строк) и создавать новую функцию, объединенную из имен ТОЛЬКО КОГДА уровень == 4 , Таким образом, в конечном итоге выходные данные должны выглядеть следующим образом:

code       combined_names
33235678   txt1+txt2+txt3+txt4
17980000   txt5+txt6

8-значные коды всегда связаны с уровнями, всегда код для уровня 1, например, 33000000, затем добавляются еще 2 цифры для уровня 2, например, 33230000 и скоро. Коды могут быть повсюду в кадре данных и НЕ обязательно должны быть последовательными строками, однако всегда с этим логом c.

Я сделал следующее, что верно до первого появления уровня условия = 4 (чтобы проверить замену 2-й уровень = 4 с, например, 9). Но на самом деле существует больше условий уровня = 4, и я получаю следующую ошибку:

def combined_names(code):
    code_list=[(code-code%10**x) for x in [6,4,2,0]]

    #above I obtain the codes correspond to level 1 to level4 when level=4 is 
    #satisfied, by difference and modulo operator to 10**6, 
    #10**4,10**2,1. e.g For 33235678 as input we get: 
    #33000000,33230000,33235600 and 33235678   

    print(code_list)
    name1=df11.query('code == @code_list[0]')['Name'].tolist()
    name2=df11.query('code == @code_list[1]')['Name'].tolist()
    name3=df11.query('code == @code_list[2]')['Name'].tolist()
    name4=df11.query('code == @code_list[3]')['Name'].tolist()

    name_list=name1+name2+name3+name4
    print(name_list)

    all_names= ' + '.join(name_list)
    return all_names
combined_names(33235678)

conditions = [df11['level'] == 4]
choices = [combined_names( df11.query('level==4')['code'].item() )] 
# problem: if there are more than one level4, then it does NOT iterate over.

# CHECK : https://stackoverflow.com/questions/16476924/how-to-iterate-over-rows-in-a-dataframe-in-pandas

df11['all_names'] = np.select(conditions, choices, default='NaN')
print(df11) 

ValueError: can only convert an array of size 1 to a Python scalar

Как изменить функцию, чтобы перехватить ВСЕ желаемые условия в df? В общем, что является более оптимизированным способом решения этой задачи? Спасибо!

1 Ответ

0 голосов
/ 15 марта 2020

Создайте временный столбец, который проверяет, равен ли уровень 4

df11['level_4'] = df11.loc[df11['level']==4,'Name']

Обратная заливка, чтобы связать с предыдущими строками

df11 = df11.bfill()

Группирование по уровню_4 и агрегирование с использованием string cat

M = df11.groupby('level_4').Name.agg(lambda x: x.str.cat(sep='+'))
M = M.rename('combined_names')

объединить с исходным фреймом данных

     (df11[['code','Name']]
      .merge(M,left_on='Name',right_on='level_4')
      .drop('Name',axis=1)
      )

    code    combined_names
0   33235678    txt1+txt2+txt3+txt4
1   17980000    txt5+txt6
...