Unpivot pandas DataFrame 部分
Unpivot pandas DataFrame partly
我有以下 table DataFrame
Items
Description
Store 1 Qty
Store 1 Value
Store 2 Qty
Store 2 Value
item 1
Some item name
5
120
7
240
item 2
Some other item
9
1234
12
98
在 Python 上是否有任何简单的方法来仅逆向存储?
这样做:
Items
Description
Store number
Value
Qty
Item 1
Some item name
Store 1
5
120
我正在考虑完全取消它的旋转,然后将它旋转回来,保持价值和数量作为价值。但我认为,应该有一些更有效的解决方案
如果需要 Qty, Value
分隔列,将第一列转换为 MultiIndex
,因此可以使用 Series.str.rsplit
by last space to MultiIndex in columns
, so last reshape by DataFrame.stack
:
df = df.set_index(['Items','Description'])
df.columns = df.columns.str.rsplit(n=1, expand=True)
df = df.rename_axis(('Store number',None), axis=1).stack(0).reset_index()
print (df)
Items Description Store number Qty Value
0 item 1 Some item name Store 1 5 120
1 item 1 Some item name Store 2 7 240
2 item 2 Some other item Store 1 9 1234
3 item 2 Some other item Store 2 12 98
您可以将 pd.melt()
与 pd.pivot
一起使用,如下所示:
df_ = pd.melt(df, id_vars=['Items', 'Description'])
df_[['Store number', 'Type']] = df_['variable'].str.rsplit(n=1, expand=True)
df_ = df_.pivot(index=['Items', 'Description', 'Store number'], columns='Type', values='value').reset_index()
print(df_)
Type Items Description Store number Qty Value
0 item 1 Some item name Store 1 5 120
1 item 1 Some item name Store 2 7 240
2 item 2 Some other item Store 1 9 1234
3 item 2 Some other item Store 2 12 98
一个选项是pd.wide_to_long
;首先必须对列进行重新排序,以便 Qty
和 Value
出现在前面:
columns = df.columns.str.rsplit(n=1).str[::-1].str.join(' ')
temp = df.set_axis(columns, axis = 'columns')
(pd.wide_to_long(temp,
stubnames = ['Qty', 'Value'],
i = ['Items', 'Description'],
j = 'Store Number',
sep = ' ',
suffix='.+')
.reset_index()
)
Items Description Store Number Qty Value
0 item 1 Some item name Store 1 5 120
1 item 1 Some item name Store 2 7 240
2 item 2 Some other item Store 1 9 1234
3 item 2 Some other item Store 2 12 98
下面是另一种可能的选择:
#pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
import pandas as pd
import janitor
df.pivot_longer(index = ['Items', 'Description'],
names_to = ('Store Number', '.value'),
names_pattern = r"(.+\s\d)\s(.+)")
Items Description Store Number Qty Value
0 item 1 Some item name Store 1 5 120
1 item 2 Some other item Store 1 9 1234
2 item 1 Some item name Store 2 7 240
3 item 2 Some other item Store 2 12 98
这使用了 pivot_longer function from pyjanitor.
说明:您希望重塑的列有一个模式(商店编号后跟 Qty 或 Value);我们在 names_pattern
中利用这一点,使用组的正则表达式 (r"(.+\s\d)\s(.+)"
) - 第一组指向 Store 1/Store2
,而另一组指向 Qty/Value
。
names_to
参数指定新数据框的外观 - 对于这种特定情况,.value
告诉函数将与其关联的部分列保留为 header - 在这种情况下,.value
是第二个条目,因此它与 names_pattern
中的第二组配对; names_to
中的 store number
与 names_pattern
中的第一个条目配对
我有以下 table DataFrame
Items | Description | Store 1 Qty | Store 1 Value | Store 2 Qty | Store 2 Value |
---|---|---|---|---|---|
item 1 | Some item name | 5 | 120 | 7 | 240 |
item 2 | Some other item | 9 | 1234 | 12 | 98 |
在 Python 上是否有任何简单的方法来仅逆向存储? 这样做:
Items | Description | Store number | Value | Qty |
---|---|---|---|---|
Item 1 | Some item name | Store 1 | 5 | 120 |
我正在考虑完全取消它的旋转,然后将它旋转回来,保持价值和数量作为价值。但我认为,应该有一些更有效的解决方案
如果需要 Qty, Value
分隔列,将第一列转换为 MultiIndex
,因此可以使用 Series.str.rsplit
by last space to MultiIndex in columns
, so last reshape by DataFrame.stack
:
df = df.set_index(['Items','Description'])
df.columns = df.columns.str.rsplit(n=1, expand=True)
df = df.rename_axis(('Store number',None), axis=1).stack(0).reset_index()
print (df)
Items Description Store number Qty Value
0 item 1 Some item name Store 1 5 120
1 item 1 Some item name Store 2 7 240
2 item 2 Some other item Store 1 9 1234
3 item 2 Some other item Store 2 12 98
您可以将 pd.melt()
与 pd.pivot
一起使用,如下所示:
df_ = pd.melt(df, id_vars=['Items', 'Description'])
df_[['Store number', 'Type']] = df_['variable'].str.rsplit(n=1, expand=True)
df_ = df_.pivot(index=['Items', 'Description', 'Store number'], columns='Type', values='value').reset_index()
print(df_)
Type Items Description Store number Qty Value
0 item 1 Some item name Store 1 5 120
1 item 1 Some item name Store 2 7 240
2 item 2 Some other item Store 1 9 1234
3 item 2 Some other item Store 2 12 98
一个选项是pd.wide_to_long
;首先必须对列进行重新排序,以便 Qty
和 Value
出现在前面:
columns = df.columns.str.rsplit(n=1).str[::-1].str.join(' ')
temp = df.set_axis(columns, axis = 'columns')
(pd.wide_to_long(temp,
stubnames = ['Qty', 'Value'],
i = ['Items', 'Description'],
j = 'Store Number',
sep = ' ',
suffix='.+')
.reset_index()
)
Items Description Store Number Qty Value
0 item 1 Some item name Store 1 5 120
1 item 1 Some item name Store 2 7 240
2 item 2 Some other item Store 1 9 1234
3 item 2 Some other item Store 2 12 98
下面是另一种可能的选择:
#pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
import pandas as pd
import janitor
df.pivot_longer(index = ['Items', 'Description'],
names_to = ('Store Number', '.value'),
names_pattern = r"(.+\s\d)\s(.+)")
Items Description Store Number Qty Value
0 item 1 Some item name Store 1 5 120
1 item 2 Some other item Store 1 9 1234
2 item 1 Some item name Store 2 7 240
3 item 2 Some other item Store 2 12 98
这使用了 pivot_longer function from pyjanitor.
说明:您希望重塑的列有一个模式(商店编号后跟 Qty 或 Value);我们在 names_pattern
中利用这一点,使用组的正则表达式 (r"(.+\s\d)\s(.+)"
) - 第一组指向 Store 1/Store2
,而另一组指向 Qty/Value
。
names_to
参数指定新数据框的外观 - 对于这种特定情况,.value
告诉函数将与其关联的部分列保留为 header - 在这种情况下,.value
是第二个条目,因此它与 names_pattern
中的第二组配对; names_to
中的 store number
与 names_pattern