Панды: переименование Безымянный: * или NaN во фрейме данных

Вот мой код:

import numpy as np
import pandas as pd
df = pd.read_excel(r'file.xlsx', index_col=0)

Вот как это выглядит: введите здесь описание изображения

Я хочу переименовать столбцы «Без имени: *» на последнее действительное имя.

Вот что я пробовал и результаты:

df.columns = df.columns.str.replace('Unnamed.*', method='ffill')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-253-c868b8bff7c7> in <module>()
----> 1 df.columns = df.columns.str.replace('Unnamed.*', method='ffill')

TypeError: replace() got an unexpected keyword argument 'method'

Это "работает", если я просто делаю

df.columns = df.columns.str.replace('Unnamed.*', '')

Но тогда у меня есть либо пустые значения, либо NaN (если я заменю '' на 'NaN'. И затем я попробую:

df.columns = df.columns.fillna('ffill')

Что не имеет никакого эффекта. Итак, я попытался с inplace=True:

df.columns = df.columns.fillna('ffill', inplace=True)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-279-cce486472d5b> in <module>()
----> 1 df.columns = df.columns.fillna('ffill', inplace=True)

TypeError: fillna() got an unexpected keyword argument 'inplace'

Тогда я попробовал по-другому:

i = 0
while i < len(df.columns):
    if df.columns[i] == 'NaN':
        df.columns[i] = df.columns[i-1]
    print(df.columns[i])
    i += 1

Что дает мне эту ошибку:

Oil
158 RGN Mistura
Access West Winter Blend 

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-246-bc8fa6881b1a> in <module>()
      2 while i < len(df.columns):
      3     if df.columns[i] == 'NaN':
----> 4         df.columns[i] = df.columns[i-1]
      5     print(df.columns[i])
      6     i += 1

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\indexes\base.py in __setitem__(self, key, value)
   2048 
   2049     def __setitem__(self, key, value):
-> 2050         raise TypeError("Index does not support mutable operations")
   2051 
   2052     def __getitem__(self, key):

TypeError: Index does not support mutable operations

person Mitch    schedule 20.06.2018    source источник


Ответы (3)


Я сделал следующее, я думаю, что он поддерживает порядок, который вы ищете.

df = pd.read_excel('book1.xlsx')
print df


    a   b   c  Unnamed: 3  Unnamed: 4   d  Unnamed: 6   e  Unnamed: 8   f
0  34  13  73         nan         nan  87         nan  76         nan  36
1  70  48   1         nan         nan  88         nan   2         nan  77
2  37  62  28         nan         nan   2         nan  53         nan  60
3  17  97  78         nan         nan  69         nan  93         nan  48
4  65  19  96         nan         nan  72         nan   4         nan  57
5  63   6  86         nan         nan  14         nan  20         nan  51
6  10  67  54         nan         nan  52         nan  48         nan  79


df.columns = pd.Series([np.nan if 'Unnamed:' in x else x for x in df.columns.values]).ffill().values.flatten()
print df


    a   b   c   c   c   d   d   e   e   f
0  34  13  73 nan nan  87 nan  76 nan  36
1  70  48   1 nan nan  88 nan   2 nan  77
2  37  62  28 nan nan   2 nan  53 nan  60
3  17  97  78 nan nan  69 nan  93 nan  48
4  65  19  96 nan nan  72 nan   4 nan  57
5  63   6  86 nan nan  14 nan  20 nan  51
6  10  67  54 nan nan  52 nan  48 nan  79
person Dickster    schedule 20.06.2018

Проблема, с которой вы столкнулись, связана с тем, что столбцы и индекс являются pd.Index объектами. Метод fillna индекса pandas не принимает те же аргументы, что и методы fillna для серий pandas или DataFrame. Я сделал игрушечный пример ниже:

import pandas as pd
import numpy as np
df = pd.DataFrame(
         {'a':[1], 'Unnamed:1':[1], 'Unnamed:2':[1], 'b':[1], 'Unnamed:3':[1]}, 
         columns=['a', 'Unnamed:3', 'Unnamed:1', 'b', 'Unnamed:2']))
df 
#   a  Unnamed:3  Unnamed:1  b  Unnamed:2
#0  1          1          1  1          1

Исходное регулярное выражение не захватывает полное имя столбца, давайте это исправим.

df.columns.str.replace('Unnamed:*', '') 
#Index(['a', '3', '1', 'b', '2'], dtype='object')
df.columns.str.replace('Unnamed:\d+', '')
#Index(['a', '', '', 'b', ''], dtype='object')
df.columns.str.replace('Unnamed:.+', '')
#Index(['a', '', '', 'b', ''], dtype='object')

Теперь давайте преобразуем индекс в ряд, чтобы мы могли использовать методы .replace и .fillna из pd.Series и одно из рабочих регулярных выражений для замены рассматриваемых имен столбцов на ffill. Наконец, мы конвертируем в pd.Index

pd.Index(
    pd.Series(
        df.columns
    ).replace('Unnamed:\d+', np.nan, regex=True).fillna(method='ffill')
)
#Index(['a', 'a', 'a', 'b', 'b'], dtype='object')

df.columns = pd.Index(pd.Series(df.columns).replace('Unnamed:\d+', np.nan, regex=True).fillna(method='ffill'))
df.head() 
#   a  a  a  b  b
#0  1  1  1  1  1
person tobsecret    schedule 20.06.2018
comment
Почему-то это не сработало. Я не получаю никаких ошибок, он просто не вносит никаких изменений в фрейм данных. Должен ли я где-то поставить inplace=True? (Когда я пытаюсь это сделать, я получаю сообщение об ошибке) - person Mitch; 21.06.2018
comment
Хм... мой пример кода вам не подходит? Вам просто нужны следующие три строки: df = pd.DataFrame( {'a':[1], 'Unnamed:1':[1], 'Unnamed:2':[1], 'b':[1], 'Unnamed:3':[1]}, columns=['a', 'Unnamed:3', 'Unnamed:1', 'b', 'Unnamed:2'])) df.columns = pd.Index(pd.Series(df.columns).replace('Unnamed:\d+', np.nan, regex=True).fillna(method='ffill')) df.head() - person tobsecret; 21.06.2018

Что-то, что могло бы сработать:

df.columns = df.columns.where(~df.columns.str.startswith('Unnamed')).to_series().ffill()

, полный пример:

import numpy as np
import pandas as pd

df = pd.DataFrame(columns=['First', 'Unnamed: 1', 'Unnamed: 2','Second', 'Unnamed: 3'])

df.columns = df.columns.where(~df.columns.str.startswith('Unnamed')).to_series().ffill()

print(df.columns)

Отпечатки:

Index(['First', 'First', 'First', 'Second', 'Second'], dtype='object')
person Anton vBR    schedule 20.06.2018