UserWarning: Pandas не позволяет создавать столбцы с помощью нового имени атрибута - PullRequest
0 голосов
/ 01 сентября 2018

Я застрял со своим сценарием для панд.

На самом деле, я работаю с двумя CSV-файлами (один входной и другой выходной файл). я хочу скопировать все строки в два столбца и сделать расчет, а затем скопировать его в другой фрейм данных (выходной файл).

Столбцы следующие:

'lat', 'long','PHCount', 'latOffset_1', 'longOffset_1','PH_Lat_1', 'PH_Long_1', 'latOffset_2', 'longOffset_2', 'PH_Lat_2', 'PH_Long_2', 'latOffset_3', 'longOffset_3','PH_Lat_3', 'PH_Long_3',  'latOffset_4', 'longOffset_4','PH_Lat_4', 'PH_Long_4'.

Я хочу взять столбцы 'lat' и 'latOffset_1', выполнить некоторые вычисления и поместить их в другой новый столбец ('PH_Lat_1'), который я уже создал.

Моя функция:

def calculate_latoffset(latoffset):  #Calculating Lat offset.
    a=(df2['lat']-(2*latoffset))
    return a

Основной код:

for i in range(1,5):
        print(i)
        a='PH_lat_%d' % i 
        print (a)
        b='latOffset_%d' % i
        print (b)
        df2.a = df2.apply(lambda x: calculate_latoffset(x[b]), axis=1)

Поскольку названия столбцов отличаются только на (1,2,3,4). поэтому я хочу вызвать функцию Calculate_latoffset и вычислить все строки всех столбцов (PH_Lat_1, PH_Lat_2, PH_Lat_3, PH_Lat_4) за один раз.

При использовании приведенного выше кода я получаю эту ошибку:

basic_conversion.py:46: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
  df2.a = df2.apply(lambda x: calculate_latoffset(x[b]), axis=1)

это возможно? Пожалуйста, помогите

Ответы [ 4 ]

0 голосов
/ 08 марта 2019

Это предупреждение, а не ошибка, поэтому ваш код все еще может выполняться, но, вероятно, не соответствует вашим намерениям.

  1. Краткий ответ: Чтобы создать новый столбец для DataFrame, никогда не использовать доступ к атрибуту , правильный способ - использовать [] или .loc индексирование :

    >>> df
       a  b
    0  7  6
    1  5  8
    >>> df['c'] = df.a + df.b 
    >>> # OR
    >>> df.loc[:, 'c'] = df.a + df.b
    >>> df # c is an new added column
       a  b   c
    0  7  6  13
    1  5  8  13
    

Более подробное объяснение: Seires и DataFrame являются базовыми классами и структурами данных в пандах, и, конечно же, они также являются классами Python, поэтому при доступе к атрибутам между пандами DataFrame и обычными объектами Python есть некоторые незначительные различия. Но это хорошо документировано и может быть легко понято. Несколько замечаний:

  1. В Python пользователи могут динамически добавлять собственные атрибуты данных к объекту экземпляра, используя доступ к атрибутам.

    >>> class Dog(object):
    ...     pass
    >>> dog = Dog()
    >>> vars(dog)
    {}
    >>> superdog = Dog()
    >>> vars(superdog)
    {}
    >>> dog.legs = 'I can run.'
    >>> superdog.wings = 'I can fly.'
    >>> vars(dog)
    {'legs': 'I can run.'}
    >>> vars(superdog)
    {'wings': 'I can fly.'}
    
  2. В пандах index и column тесно связаны со структурой данных, вы можете получить доступ к index для серии, столбец для DataFrame как атрибут .

    >>> import pandas as pd
    >>> import numpy as np
    >>> data = np.random.randint(low=0, high=10, size=(2,2))
    >>> df = pd.DataFrame(data, columns=['a', 'b'])
    >>> df
       a  b
    0  7  6
    1  5  8
    >>> vars(df)
    {'_is_copy': None, 
     '_data': BlockManager
        Items: Index(['a', 'b'], dtype='object')
        Axis 1: RangeIndex(start=0, stop=2, step=1)
        IntBlock: slice(0, 2, 1), 2 x 2, dtype: int64,
     '_item_cache': {}}
    
  3. Но доступ к атрибуту pandas - это , в основном удобное для чтения и изменения существующего элемента Серии или столбца DataFrame.

    >>> df.a
    0    7
    1    5
    Name: a, dtype: int64
    >>> df.b = [1, 1]
    >>> df
       a  b
    0  7  1
    1  5  1
    
  4. И, удобство является компромиссом для полной функциональности. Например. Вы можете создать объект DataFrame с именами столбцов ['space bar', '1', 'loc', 'min', 'index'], но не можете получить к ним доступ как к атрибуту, поскольку они либо не являются допустимым идентификатором Python 1, space bar, либо конфликтуют с существующим именем метода.

    >>> data = np.random.randint(0, 10, size=(2, 5))
    >>> df_special_col_names = pd.DataFrame(data, columns=['space bar', '1', 'loc', 'min', 'index'])
    >>> df_special_col_names
       space bar  1  loc  min  index
    0          4  4    4    8      9
    1          3  0    1    2      3
    
  5. В этих случаях индексирование .loc, .iloc и [] является определенным способом для полного доступа / работы с индексом и столбцами объектов Series и DataFrame.

    >>> df_special_col_names['space bar']
    0    4
    1    3
    Name: space bar, dtype: int64
    >>> df_special_col_names.loc[:, 'min']
    0    8
    1    2
    Name: min, dtype: int64
    >>> df_special_col_names.iloc[:, 1]
    0    4
    1    0
    Name: 1, dtype: int64
    
  6. Что касается темы, то, как вы можете видеть, чтобы создать новый столбец для DataFrame, df.c = df.a + df.b просто создал новый атрибут вдоль основной структуры данных , поэтому начиная с версии 0.21.0 и выше, это поведение вызовет UserWarning (больше ничего не будет).

    >>> df
       a  b
    0  7  1
    1  5  1
    >>> df.c = df.a + df.b
    __main__:1: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
    >>> df['d'] = df.a + df.b
    >>> df
       a  b  d
    0  7  1  8
    1  5  1  6
    >>> df.c
    0    8
    1    6
    dtype: int64
    >>> vars(df)
    {'_is_copy': None, 
     '_data': 
        BlockManager
        Items: Index(['a', 'b', 'd'], dtype='object')
        Axis 1: RangeIndex(start=0, stop=2, step=1)
        IntBlock: slice(0, 2, 1), 2 x 2, dtype: int64
        IntBlock: slice(2, 3, 1), 1 x 2, dtype: int64, 
     '_item_cache': {},
     'c': 0    8
          1    6
          dtype: int64}
    
  7. Наконец, вернемся к краткому ответу.

0 голосов
/ 01 сентября 2018

Решение, которое я могу придумать, - использовать .loc для получения столбца. Вы можете попробовать df.loc[:,a] вместо df.a. Столбцы данных Pandas не могут быть созданы с использованием точечного метода, чтобы избежать потенциальных конфликтов с атрибутами dataframe. Надеюсь, это поможет

0 голосов
/ 16 ноября 2018

Просто используйте df2['a'] вместо df2.a

0 голосов
/ 01 сентября 2018

В df2.apply(lambda x: calculate_latoffset(x[b]), axis=1) вы создаете 5-колоночный фрейм данных и пытаетесь присвоить значение одному полю. Do df2[a] = calculate_latoffset(df2[b]) вместо этого должен выдать желаемый результат.

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