Они довольно похожи с некоторыми небольшими отличиями, во-первых, это переменная, которая назначается анонимной функции (Объявление функции), а вторая - обычным способом создания функции в 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 / Глоссарий / Подъемно
Я думаю, что самый простой способ сделать это - установить столбцы на верхний уровень:
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']
Если вы хотите иметь разделитель в имени между уровнями, эта функция работает хорошо.
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)
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
pd.DataFrame(df.to_records(), columns=df.index.names + list(df.columns))
– Teoretic
3 August 2018 в 10:13
Общее решение, которое обрабатывает несколько уровней и смешанных типов:
df.columns = ['_'.join(tuple(map(str, t))) for t in df.columns.values]
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
Прочитав все ответы, я придумал следующее:
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
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
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
map(str, ..)
filter(None, ..)
columns.values
возвращает имена (str
, а не кортежи) .agg()
, вам может понадобиться чтобы удерживать нижнюю метку для столбца или конкатенировать несколько ярлыков reset_index()
мог работать с группой- по столбцам в обычном порядке, поэтому он делает это по умолчанию 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()
(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
Самый пифонический способ сделать это для использования функции 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')
Ответ Энди Хайдена, безусловно, самый простой способ - если вы хотите избежать дублирования ярлыков столбцов, вам нужно немного настроить
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
df.columns = ['_'.join(tup).rstrip('_') for tup in df.columns.values]
Вы также можете сделать так, как показано ниже. Рассмотрим df
как ваш фрейм данных и предположим двухуровневый индекс (как в вашем примере)
df.columns = [(df.columns[i][0])+'_'+(datadf_pos4.columns[i][1]) for i in range(len(df.columns))]
['_'.join(col).rstrip('_') for col in df.columns.values]
– Seiji Armstrong 13 February 2018 в 20:02