Редактировать: 21 ноября 2022 г.
Как нам связать df.col.str.split()
, так как это возвращает разделенные столбцы, если expand = True
Я пытаюсь разделить столбец после выполнения .melt()
. Если я использую assign, я в конечном итоге использую исходный столбец, а расплавленный столбец на самом деле даже не существует.
df = pd.DataFrame().from_dict({
'id' : [1,2,3,4],
'2022_amt' : [10.1,20.2,30.3, 40.4],
'2022_qty' : [10,20,30,40]
})
df = (
df
.melt(
id_vars=['id'],
value_vars=['2022_amt', '2022_qty'],
var_name='fy',
value_name='num'
)
# can i chain any pd.Series.str.[METHOD] here
# .assign(
# year=df.fy.str.split('_', expand=True)[0],
# t=df.fy.str.split('_', expand=True)[1]
# )
)
# i can add the two columns in this way but can we use chain to expand dataframe df
df[['year', 't']] = df.fy.str.split('_', expand=True)
df = df.drop(columns = ['fy'])
отличная идея так и сделал
Не уверен, что вы пытаетесь сделать.
Но в чем я уверен, так это в том, что вы не можете использовать [0]
(по крайней мере, не делать то, что хотите) непосредственно в сериале. Но вы можете снова вызвать .str
, чтобы использовать [0]
операторов
Пример
df=pd.DataFrame({'s':['abc-def|ghi', 'one-two|three']})
df.s.str.split('-').str[0]
#0 abc
#1 one
#Name: s, dtype: object
df.s.str.split('-').str[1].str.split('|').str[0]
#0 def
#1 two
#Name: s, dtype: object
df.s.str.split('-').str[1].str.split('|').str[1]
#0 ghi
#1 three
#Name: s, dtype: object
Обратите внимание, что половина .str
здесь нелогична, поскольку на самом деле мы не используем строковые функции для результата (которые являются массивами). Но .str
также работает с массивами и со всем, что использует индексацию [..]
. Пока вы не вызываете специфичную для строки функцию. Итак, это трюк: .str
в серии позволяет вызывать строковые методы для элементов серии. И некоторые из строковых методов, включая индексацию, также имеют значение для массивов.
Использование expand
преобразует его в DataFrame, что вам здесь не очень нужно; во-вторых, с цепочкой используйте анонимную функцию для ссылки на предыдущий фрейм данных:
(df
.melt(id_vars='id',var_name='fy',value_name='num')
assign(year = lambda df: df.fy.str.split('_').str[0],
t = lambda df: df.fy.str.split('_').str[1])
)
id fy num year t
0 1 2022_amt 10.1 2022 amt
1 2 2022_amt 20.2 2022 amt
2 3 2022_amt 30.3 2022 amt
3 4 2022_amt 40.4 2022 amt
4 1 2022_qty 10.0 2022 qty
5 2 2022_qty 20.0 2022 qty
6 3 2022_qty 30.0 2022 qty
7 4 2022_qty 40.0 2022 qty
Для вашего варианта использования есть более простые и эффективные способы сделать это:
pd.stack
:df = df.set_index('id')
df.columns = df.columns.str.split('_', expand = True)
df.columns.names = ['year', 't']
df.stack(['year', 't']).reset_index(name='num')
id year t num
0 1 2022 amt 10.1
1 1 2022 qty 10.0
2 2 2022 amt 20.2
3 2 2022 qty 20.0
4 3 2022 amt 30.3
5 3 2022 qty 30.0
6 4 2022 amt 40.4
7 4 2022 qty 40.0
pivot_longer
из pyjanitor
:# pip install pyjanitor
import pandas as pd
import janitor as jn
df.pivot_longer(index = 'id', names_to = ('year','t'), names_sep = '_')
id year t value
0 1 2022 amt 10.1
1 2 2022 amt 20.2
2 3 2022 amt 30.3
3 4 2022 amt 40.4
4 1 2022 qty 10.0
5 2 2022 qty 20.0
6 3 2022 qty 30.0
7 4 2022 qty 40.0
Предоставьте образцы данных, возможно, есть более эффективный способ сделать это.