Альтернативы Dataframe.iterrows () или Dataframe.itertuples ()? - PullRequest
0 голосов
/ 31 октября 2018

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

import pandas as pd
df = pd.DataFrame({'color' : ['red','blue','yellow','orange','green',
                         'white','black','brown','orange-red','teal',
                         'beige','mauve','cyan','goldenrod','auburn',
                         'azure','celadon','lavender','oak','chocolate'], 
               'group' : [1,1,1,1,1,
                          1,1,1,1,1,
                          1,2,2,2,2,
                          4,4,5,6,7]})
df = df.set_index('color')
df

enter image description here

Для этих данных я хочу применить специальный счетчик для каждого уникального значения в A. Вот моя текущая реализация:

df['C'] = 0
for value in set(df['group'].values):
    filtered_df = df[df['group'] == value]
    adj_counter = 0
    initialize_counter = -1
    spacing_counter = 20
    special_counters = [0,1,-1,2,-2,3,-3,4,-4,5,-5,6,-6,7,-7]
    for color,rows in filtered_df.iterrows():
        if len(filtered_df.index) < 7:
            initialize_counter +=1
            df.loc[color,'C'] = (46+special_counters[initialize_counter])

        else:
            spacing_counter +=1
            if spacing_counter > 5:
                spacing_counter = 0
            df.loc[color,'C'] = spacing_counter
df

enter image description here

Есть ли более быстрый способ реализовать это, не задействуя iterrows или itertuples? Поскольку подсчет в столбцах C очень нерегулярен, я не уверен, как я мог бы реализовать это с помощью применения или даже векторизации

1 Ответ

0 голосов
/ 31 октября 2018

Что вы можете сделать, это сначала создать столбец 'C' с groupby в столбце 'group' и cumcount, который бы почти представлял spacing_counter или initialize_counter в зависимости от if len(filtered_df.index) < 7 или нет.

df['C'] = df.groupby('group').cumcount()

Теперь вам нужно выбрать соответствующие строки для выполнения части кода if или else. Один из способов - создать серию снова, используя groupby и transform, чтобы узнать size группы, связанной с каждой строкой. Затем используйте loc на вас df, используя эту серию, и сделайте следующее: если значение меньше 7, вы можете map свои значения с помощью special_counters, иначе просто используйте модуль % 6

ser_size = df.groupby('group')['C'].transform('size')
df.loc[ser_size < 7,'C'] = df.loc[ser_size < 7,'C'].map(lambda x: 46 + special_counters[x])
df.loc[ser_size >= 7,'C'] %= 6

в конце вы получите, как и ожидалось:

print (df)
            group   C
color                
red             1   0
blue            1   1
yellow          1   2
orange          1   3
green           1   4
white           1   5
black           1   0
brown           1   1
orange-red      1   2
teal            1   3
beige           1   4
mauve           2  46
cyan            2  47
goldenrod       2  45
auburn          2  48
azure           4  46
celadon         4  47
lavender        5  46
oak             6  46
chocolate       7  46
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...