Я хочу добавить полные поля в этот DataFrame:

df_test = pd.DataFrame([
    {'id':1,'cat1a':3,'cat1b':2, 'cat2a':4,'cat2b':3},
    {'id':2,'cat1a':7,'cat1b':5, 'cat2a':9,'cat2b':6}
])

Этот код почти работает:

 def add_total(therecord):
        t1 = therecord['cat1a'] + therecord['cat1b']
        t2 = therecord['cat2a'] + therecord['cat2b']
        return t1, t2

df_test['cat1tot', 'cat2tot'] = df_test[['cat1a', 'cat1b', 'cat2a', 'cat2b']].apply(add_total,axis=1)

Кроме того, это приводит только к 1 новому столбцу:

enter image description here

И этот код:

 def add_total(therecord):
        t1 = therecord['cat1a'] + therecord['cat1b']
        t2 = therecord['cat2a'] + therecord['cat2b']
        return [t1, t2]

df_test[['cat1tot', 'cat2tot']] = df_test[['cat1a', 'cat1b', 'cat2a', 'cat2b']].apply(add_total,axis=1)

Результаты в: KeyError: "['cat1tot' 'cat2tot'] not in index"

Я попытался решить это с:

my_cols_list=['cat1tot','cat2tot']
df_test.reindex(columns=[*df_test.columns.tolist(), *my_cols_list], fill_value=0)

Но это не решило проблему. Так чего мне не хватает?

1
Brad Rhoads 27 Фев 2018 в 22:24

3 ответа

Лучший ответ

Как правило, не хорошая идея использовать df.apply, если вы абсолютно не обязаны это делать. Причина в том, что эти операции не векторизованы, то есть в фоновом режиме есть цикл, в котором каждая строка подается в функцию как ее собственный pd.Series.

Это будет векторизованная реализация:

df_test['cat1tot'] = df_test['cat1a'] + df_test['cat1b']
df_test['cat2tot'] = df_test['cat2a'] + df_test['cat2b']

#    cat1a  cat1b  cat2a  cat2b  id  cat1tot  cat2tot
# 0      3      2      4      3   1        5        7
# 1      7      5      9      6   2       12       15
2
jpp 27 Фев 2018 в 19:35

Как насчет

df_test['cat1tot'], df_test['cat2tot'] =\
   df_test[['cat1a', 'cat1b', 'cat2a', 'cat2b']].apply(add_total,axis=1)
1
mortysporty 27 Фев 2018 в 19:29

Вместо этого верните Series объект:

def add_total(therecord):
    t1 = therecord['cat1a'] + therecord['cat1b']
    t2 = therecord['cat2a'] + therecord['cat2b']

    return pd.Series([t1, t2])

А потом,

df_test[['cat1tot', 'cat2tot']] = \
      df_test[['cat1a', 'cat1b', 'cat2a', 'cat2b']].apply(add_total,axis=1)

df_test

   cat1a  cat1b  cat2a  cat2b  id  cat1tot  cat2tot
0      3      2      4      3   1        5        7
1      7      5      9      6   2       12       15

Это работает, потому что apply будет в особом случае возвращать тип Series и предполагать, что вы хотите получить результат в виде среза кадра данных.

2
cs95 27 Фев 2018 в 19:35