Переименовать столбец автоматически, чтобы сделать его машиной для обучения дружественным [дублировать]

Они довольно похожи с некоторыми небольшими отличиями, во-первых, это переменная, которая назначается анонимной функции (Объявление функции), а вторая - обычным способом создания функции в JavaScript (анонимная декларация функции), у обоих есть использование, минусы и плюсы:

1. Функция Expression

var functionOne = function() {
    // Some code
};

Функция Expression определяет функцию как часть синтаксиса большего выражения (обычно назначение переменной). Функции, определенные с помощью функций Выражения, можно назвать или анонимными. Выражения функции не должны начинаться с «функции» (следовательно, круглые скобки вокруг примера самозапуска).

Назначить переменную функции, значит нет Подъем, так как мы знаем, что функции в JavaScript могут Hoist, означает, что их можно вызвать до того, как они будут объявлены, а переменные должны быть объявлены до получения доступа к ним, поэтому в этом случае мы не можем получить доступ к функции до того, где она объявлена, также это может быть способ, которым вы пишете свои функции для функций, возвращающих другую функцию, такая декларация может иметь смысл, также в ECMA6 & amp; выше вы можете назначить это функции стрелки, которая может использоваться для вызова анонимных функций, также этот способ объявления - лучший способ создания функций конструктора в JavaScript.

2. Объявление функции

function functionTwo() {
    // Some code
}

Объявление функции определяет именованную функциональную переменную без необходимости назначения переменной. Объявление функций происходит как автономные конструкции и не может быть вложено внутри не-функциональных блоков. Полезно подумать о них как о братьях и сестрах переменных объявлений. Так же, как объявления переменных должны начинаться с «var», декларации функций должны начинаться с «функции».

Это обычный способ вызова функции в JavaScript, эта функция может быть вызвана перед вами даже объявите его, как и в JavaScript, все функции получают Hoisted, но если вы используете «strict», это не будет Hoist, как ожидалось, это хороший способ вызвать все обычные функции, которые не являются большими в строках и не являются конструкторской функцией.

Кроме того, если вам нужна дополнительная информация о том, как работает подъем в JavaScript, перейдите по ссылке ниже:

https://developer.mozilla.org/en-US/docs / Глоссарий / Подъемно

164
задан Mark Byers 14 May 2013 в 12:53
поделиться

13 ответов

Я думаю, что самый простой способ сделать это - установить столбцы на верхний уровень:

df.columns = df.columns.get_level_values(0)

Примечание: если на уровне есть имя, вы также можете получить к нему доступ это, а не 0.

.

Если вы хотите объединить / join ваш MultiIndex в один индекс ( предполагая, что у вас есть только строковые записи в ваших столбцах) вы могли бы:

df.columns = [' '.join(col).strip() for col in df.columns.values]

Примечание: мы должны strip пробелы, когда есть нет второго индекса.

In [11]: [' '.join(col).strip() for col in df.columns.values]
Out[11]: 
['USAF',
 'WBAN',
 'day',
 'month',
 's_CD sum',
 's_CL sum',
 's_CNT sum',
 's_PC sum',
 'tempf amax',
 'tempf amin',
 'year']
244
ответ дан Andy Hayden 21 August 2018 в 03:45
поделиться
  • 1
    df.reset_index (inplace = True) может быть альтернативным решением. – Tobias 7 June 2017 в 06:15
  • 2
    один незначительный комментарий ... если вы хотите использовать _ для многоуровневого столбца объединения, вы можете использовать это ... df.columns = ['_'. join (col) .strip () для col в df.columns. значения] – ihightower 3 July 2017 в 16:05
  • 3
    незначительная модификация для поддержания подчеркивания только для соединенных столбцов: ['_'.join(col).rstrip('_') for col in df.columns.values] – Seiji Armstrong 13 February 2018 в 20:02

Если вы хотите иметь разделитель в имени между уровнями, эта функция работает хорошо.

def flattenHierarchicalCol(col,sep = '_'):
    if not type(col) is tuple:
        return col
    else:
        new_col = ''
        for leveli,level in enumerate(col):
            if not level == '':
                if not leveli == 0:
                    new_col += sep
                new_col += level
        return new_col

df.columns = df.columns.map(flattenHierarchicalCol)
3
ответ дан agartland 21 August 2018 в 03:45
поделиться
  • 1
    Мне это нравится. Оставив случай, когда столбцы не являются иерархическими, это может быть упрощено: df.columns = ["_".join(filter(None, c)) for c in df.columns] – Gigo 19 October 2016 в 22:41
pd.DataFrame(df.to_records()) # multiindex become columns and new index is integers only
49
ответ дан Gleb Yarnykh 21 August 2018 в 03:45
поделиться
  • 1
    Это работает, но оставляет имена столбцов, которые труднодоступны программно и не требуют ответа – dmeu 29 June 2017 в 08:53
  • 2
    Это не будет работать с последней версией панд. Он работает с 0,18, но не с 0,20 (последний на данный момент) – TH22 10 October 2017 в 20:59
  • 3
    @dmeu для сохранения имен столбцов pd.DataFrame(df.to_records(), columns=df.index.names + list(df.columns)) – Teoretic 3 August 2018 в 10:13
  • 4
    @ TH22 это работает для меня с версией 0.23.3 – Teoretic 3 August 2018 в 10:16

Общее решение, которое обрабатывает несколько уровней и смешанных типов:

df.columns = ['_'.join(tuple(map(str, t))) for t in df.columns.values]
2
ответ дан jxstanford 21 August 2018 в 03:45
поделиться
  • 1
    В случае наличия неиерархических столбцов: df.columns = ['_'.join(tuple(map(str, t))).rstrip('_') for t in df.columns.values] – Nolan Conaway 10 August 2017 в 20:30

И если вы хотите сохранить любую информацию об агрегировании со второго уровня мультииндекса, вы можете попробовать следующее:

In [1]: new_cols = [''.join(t) for t in df.columns]
Out[1]:
['USAF',
 'WBAN',
 'day',
 'month',
 's_CDsum',
 's_CLsum',
 's_CNTsum',
 's_PCsum',
 'tempfamax',
 'tempfamin',
 'year']

In [2]: df.columns = new_cols
5
ответ дан Mathew Savage 21 August 2018 в 03:45
поделиться

Прочитав все ответы, я придумал следующее:

def __my_flatten_cols(self, how="_".join, reset_index=True):
    how = (lambda iter: list(iter)[-1]) if how == "last" else how
    self.columns = [how(filter(None, map(str, levels))) for levels in self.columns.values] \
                    if isinstance(self.columns, pd.MultiIndex) else self.columns
    return self.reset_index() if reset_index else self
pd.DataFrame.my_flatten_cols = __my_flatten_cols

Использование:

С учетом кадра данных:

df = pd.DataFrame({"grouper": ["x","x","y","y"], "val1": [0,2,4,6], 2: [1,3,5,7]}, columns=["grouper", "val1", 2])

  grouper  val1  2
0       x     0  1
1       x     2  3
2       y     4  5
3       y     6  7
  • Метод одиночной агрегации: результирующие переменные называются такими же, как источник:
    df.groupby(by="grouper").agg("min").my_flatten_cols()
    
    То же, что и df.groupby(by="grouper", as_index = False ) или .agg(...) .reset_index ()
    ----- before -----
               val1  2
      grouper         
    
    ------ after -----
      grouper  val1  2
    0       x     0  1
    1       y     4  5
    
  • Переменная с одним источником , множественные агрегации: результирующие переменные, названные в честь статистики:
    df.groupby(by="grouper").agg({"val1": [min,max]}).my_flatten_cols("last")
    
    То же, что и a = df.groupby(..).agg(..); a.columns = a.columns.droplevel(0); a.reset_index().
    ----- before -----
                val1    
               min max
      grouper         
    
    ------ after -----
      grouper  min  max
    0       x    0    2
    1       y    4    6
    
  • Несколько переменных, множественные агрегации: результирующие переменные с именем (varname) _ (statname):
    df.groupby(by="grouper").agg({"val1": min, 2:[sum, "size"]}).my_flatten_cols()
    # you can combine the names in other ways too, e.g. use a different delimiter:
    #df.groupby(by="grouper").agg({"val1": min, 2:[sum, "size"]}).my_flatten_cols(" ".join)
    
    Запускает a.columns = ["_".join(filter(None, map(str, levels))) for levels in a.columns.values] под капотом (так как эта форма agg() приводит к MultiIndex по столбцам). Если у вас нет помощника my_flatten_cols, может быть проще ввести решение, предложенное @Seigi : a.columns = ["_".join(t).rstrip("_") for t in a.columns.values], которое работает аналогично в этом случае (но сбой, если у вас есть числовые метки для столбцов). Чтобы обрабатывать числовые метки в столбцах, вы можете использовать решение, предложенное @jxstanford и @Nolan Conaway (a.columns = ["_".join(tuple(map(str, t))).rstrip("_") for t in a.columns.values]), но я не понимаю, почему вызов tuple() и я полагаю, что rstrip() требуется только в том случае, если некоторые столбцы имеют дескриптор типа ("colname", "") (что может произойти, если вы reset_index() перед попыткой исправить .columns)
    ----- before -----
               val1           2     
               min       sum    size
      grouper              
    
    ------ after -----
      grouper  val1_min  2_sum  2_size
    0       x         0      4       2
    1       y         4     12       2
    
  • Вы хотите назвать результирующие переменные вручную: (это устарело, поскольку pandas 0.20.0 с не имеет адекватной альтернативы с 0,23 )
    df.groupby(by="grouper").agg({"val1": {"sum_of_val1": "sum", "count_of_val1": "count"},
                                       2: {"sum_of_2":    "sum", "count_of_2":    "count"}}).my_flatten_cols("last")
    
    Другое включают : установка столбцов вручную: res.columns = ['A_sum', 'B_sum', 'count'] или .join() с несколькими операторами groupby.
    ----- before -----
                       val1                      2         
              count_of_val1 sum_of_val1 count_of_2 sum_of_2
      grouper                                              
    
    ------ after -----
      grouper  count_of_val1  sum_of_val1  count_of_2  sum_of_2
    0       x              2            2           2         4
    1       y              2           10           2        12
    

Случаи, выполняемые вспомогательной функцией

  • имена уровней могут быть нестрочными, например. Индекс pandas DataFrame по номерам столбцов, когда имена столбцов являются целыми числами , поэтому нам нужно преобразовать с помощью map(str, ..)
  • , они также могут быть пустыми, поэтому мы должны filter(None, ..)
  • для одноуровневых столбцов (т. е. ничего, кроме MultiIndex), columns.values возвращает имена (str, а не кортежи)
  • в зависимости от того, как вы использовали .agg(), вам может понадобиться чтобы удерживать нижнюю метку для столбца или конкатенировать несколько ярлыков
  • (так как я новичок в пандах?) чаще, чем нет, я хочу, чтобы reset_index() мог работать с группой- по столбцам в обычном порядке, поэтому он делает это по умолчанию
3
ответ дан Nickolay 21 August 2018 в 03:45
поделиться
  • 1
    действительно отличный ответ, можете ли вы объяснить работу «[i]» .join (tuple (map (str, t))). rstrip («») для t в .columns.values] ', спасибо заранее – Vineet 26 July 2018 в 13:05
  • 2
    @Vineet Я обновил сообщение, чтобы указать, что я упомянул об этом фрагменте, чтобы предположить, что он имеет аналогичный эффект для моего решения. Если вам нужна информация о том, почему tuple() необходим, вы можете прокомментировать сообщение jxstanford. В противном случае было бы полезно проверить .columns.values в приведенном примере: [('val1', 'min'), (2, 'sum'), (2, 'size')]. 1) for t in a.columns.values петли над столбцами, для второго столбца t == (2, 'sum'); 2) map(str, t) применяет str() к каждому «уровню», что приводит к ('2', 'sum'); 3) "_".join(('2','sum')) приводит к «2_sum», – Nickolay 26 July 2018 в 17:07

Возможно, немного поздно, но если вас не беспокоят дублирующие имена столбцов:

df.columns = df.columns.tolist()
3
ответ дан Niels 21 August 2018 в 03:45
поделиться
  • 1
    Для меня это изменяет имена колонок как кортежи: (year, ) и (tempf, amax) – Nickolay 28 May 2018 в 07:44

Следуя @jxstanford и @ tvt173, я написал быструю функцию, которая должна делать трюк, независимо от имен столбцов string / int:

def flatten_cols(df):
    df.columns = [
        '_'.join(tuple(map(str, t))).rstrip('_') 
        for t in df.columns.values
        ]
    return df
2
ответ дан Nolan Conaway 21 August 2018 в 03:45
поделиться

Самый пифонический способ сделать это для использования функции map.

df.columns = df.columns.map(' '.join).str.strip()

Выход print(df.columns):

Index(['USAF', 'WBAN', 'day', 'month', 's_CD sum', 's_CL sum', 's_CNT sum',
       's_PC sum', 'tempf amax', 'tempf amin', 'year'],
      dtype='object')
0
ответ дан Scott Boston 21 August 2018 в 03:45
поделиться

Ответ Энди Хайдена, безусловно, самый простой способ - если вы хотите избежать дублирования ярлыков столбцов, вам нужно немного настроить

In [34]: df
Out[34]: 
     USAF   WBAN  day  month  s_CD  s_CL  s_CNT  s_PC  tempf         year
                               sum   sum    sum   sum   amax   amin      
0  702730  26451    1      1    12     0     13     1  30.92  24.98  1993
1  702730  26451    2      1    13     0     13     0  32.00  24.98  1993
2  702730  26451    3      1     2    10     13     1  23.00   6.98  1993
3  702730  26451    4      1    12     0     13     1  10.04   3.92  1993
4  702730  26451    5      1    10     0     13     3  19.94  10.94  1993


In [35]: mi = df.columns

In [36]: mi
Out[36]: 
MultiIndex
[(USAF, ), (WBAN, ), (day, ), (month, ), (s_CD, sum), (s_CL, sum), (s_CNT, sum), (s_PC, sum), (tempf, amax), (tempf, amin), (year, )]


In [37]: mi.tolist()
Out[37]: 
[('USAF', ''),
 ('WBAN', ''),
 ('day', ''),
 ('month', ''),
 ('s_CD', 'sum'),
 ('s_CL', 'sum'),
 ('s_CNT', 'sum'),
 ('s_PC', 'sum'),
 ('tempf', 'amax'),
 ('tempf', 'amin'),
 ('year', '')]

In [38]: ind = pd.Index([e[0] + e[1] for e in mi.tolist()])

In [39]: ind
Out[39]: Index([USAF, WBAN, day, month, s_CDsum, s_CLsum, s_CNTsum, s_PCsum, tempfamax, tempfamin, year], dtype=object)

In [40]: df.columns = ind




In [46]: df
Out[46]: 
     USAF   WBAN  day  month  s_CDsum  s_CLsum  s_CNTsum  s_PCsum  tempfamax  tempfamin  \
0  702730  26451    1      1       12        0        13        1      30.92      24.98   
1  702730  26451    2      1       13        0        13        0      32.00      24.98   
2  702730  26451    3      1        2       10        13        1      23.00       6.98   
3  702730  26451    4      1       12        0        13        1      10.04       3.92   
4  702730  26451    5      1       10        0        13        3      19.94      10.94   




   year  
0  1993  
1  1993  
2  1993  
3  1993  
4  1993
22
ответ дан Theodros Zelleke 21 August 2018 в 03:45
поделиться
  • 1
    спасибо Theodros! Это единственное правильное решение, которое обрабатывает все случаи! – CanCeylan 31 July 2017 в 13:57
  • 2
    Ты легенда! Спасибо за красивое объяснение! – Wael Hussein 13 April 2018 в 21:59
df.columns = ['_'.join(tup).rstrip('_') for tup in df.columns.values]
6
ответ дан tvt173 21 August 2018 в 03:45
поделиться

Вы также можете сделать так, как показано ниже. Рассмотрим df как ваш фрейм данных и предположим двухуровневый индекс (как в вашем примере)

df.columns = [(df.columns[i][0])+'_'+(datadf_pos4.columns[i][1]) for i in range(len(df.columns))]
-1
ответ дан user6655984 21 August 2018 в 03:45
поделиться
  • 1
    Это будет лучше читать, если вы отформатируете его лучше. – Ding 27 October 2016 в 23:37
0
ответ дан Lean Bravo 31 October 2018 в 23:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: