以双行标题为深度数据框的枢轴宽数据框
pivot wide dataframe with double row heading to deep dataframe
我有信心我可以蒙混过关,甚至可能找到一些优雅的东西,但我很好奇其他人会如何解决这个问题:
我想采用这样的数据框:
| a1 | b1 | c1 |
| ---- | ---- | --- |
| a2 | b2 | c2 |
| --- | --- | --- |
| v1 | v2 | v3 |
| ... | ... | ... |
| v100 | v101 | v102|
并转换为这样的数据框,其中 x*
是自定义的 headers,我可以提供以下列表:
| x1 | x2 | x3 |
| --- | --- | ---- |
| a1 | a2 | v1 |
| ... | ... | ... |
| a1 | a2 | v100 |
| b1 | b2 | v2 |
| ... | ... | ... |
| b1 | b2 | v101 |
| c1 | c2 | v3 |
| ... | ... | ... |
| c1 | c2 | v102 |
上下文是需要转换的 CSV 导入,但有两行 headers,在这种情况下将变为 x1
和 x2
。
非常感谢任何提示或建议!同样,有信心可以用一些肘部油脂来做到这一点,但我想提高我的旋转和 index-ing 直觉。
更新:根据评论,这里是源和目标数据框示例:
# source dataframe
df1 = pd.DataFrame(columns=['a1','b1','c1'], data=[['a2','b2','c2'],['v1','v2','v3'],['v100','v101','v102']])
"""
In [14]: df1
Out[14]:
a1 b1 c1
0 a2 b2 c2
1 v1 v2 v3
2 v100 v101 v102
"""
# target dataframe (where "x*" headers will be provided)
df2 = pd.DataFrame(columns=['x1','x2','x3'], data=[['a1','a2','v1'],['a1','a2','v100'],['b1','b2','v2'],['b1','b2','v101'],['c1','c2','v3'],['c1','c2','v102']])
"""
In [16]: df2
Out[16]:
x1 x2 x3
0 a1 a2 v1
1 a1 a2 v100
2 b1 b2 v2
3 b1 b2 v101
4 c1 c2 v3
5 c1 c2 v102
"""
如果我正确理解了您的初始 DataFrame,我可以这样创建它:
import pandas as pd
n = 100
listA = [f'V{x}' for x in range(1,n+1)]
listA.insert(0,("a1"))
listA.insert(1,"a2")
listB = [f'V{x}' for x in range(n+1,2*n+1)]
listB.insert(0,("b1"))
listB.insert(1,"b2")
listC = [f'V{x}' for x in range(2*n+1,3*n+1)]
listC.insert(0,("c1"))
listC.insert(1,"c2")
data = [listA, listB, listC]
df = pd.DataFrame(data).T
现在您创建一个包含三列的空 DataFrame:“x1”、“x2”、“x3”:
newDF = pd.DataFrame( columns=["x1", "x2", "x3"])
然后在 for 循环中添加行,选择元素在原始 DataFrame 中的位置:
for i in range(3):
for j in range(n):
row = [df.iloc[0][i],df.iloc[1][i], df.iloc[j+2][i]]
newDF.loc[len(newDF.index)] = row
希望对你有用。
更新
根据您的更新:
您从 header 列创建一个 row0 :
row0 = pd.DataFrame(list(df1.columns)).T
您更改 row0 和 df1 的列名称:
row0.columns = ["x1","x2","x3"]
df1.columns = ["x1","x2","x3"]
您在 dnew DataFrame 中连接 row0 和 df1:
dnew = pd.concat([row0, df])
您创建 df2 :
df2 = pd.DataFrame(columns=["x1", "x2", "x3"])
for i in range(len(dnew.columns)):
for j in range(len(dnew)-2):
row = [dnew.iloc[0][i],dnew.iloc[1][i], dnew.iloc[j+2][i]]
df2.loc[len(df2)] = row
这是multi-step整形:
(df1.T
.set_index(0, append=True)
.rename_axis(['x1', 'x2'])
.stack()
.droplevel(-1)
.reset_index(name='x3')
)
输出:
x1 x2 x3
0 a1 a2 v1
1 a1 a2 v100
2 b1 b2 v2
3 b1 b2 v101
4 c1 c2 v3
5 c1 c2 v102
我有信心我可以蒙混过关,甚至可能找到一些优雅的东西,但我很好奇其他人会如何解决这个问题:
我想采用这样的数据框:
| a1 | b1 | c1 |
| ---- | ---- | --- |
| a2 | b2 | c2 |
| --- | --- | --- |
| v1 | v2 | v3 |
| ... | ... | ... |
| v100 | v101 | v102|
并转换为这样的数据框,其中 x*
是自定义的 headers,我可以提供以下列表:
| x1 | x2 | x3 |
| --- | --- | ---- |
| a1 | a2 | v1 |
| ... | ... | ... |
| a1 | a2 | v100 |
| b1 | b2 | v2 |
| ... | ... | ... |
| b1 | b2 | v101 |
| c1 | c2 | v3 |
| ... | ... | ... |
| c1 | c2 | v102 |
上下文是需要转换的 CSV 导入,但有两行 headers,在这种情况下将变为 x1
和 x2
。
非常感谢任何提示或建议!同样,有信心可以用一些肘部油脂来做到这一点,但我想提高我的旋转和 index-ing 直觉。
更新:根据评论,这里是源和目标数据框示例:
# source dataframe
df1 = pd.DataFrame(columns=['a1','b1','c1'], data=[['a2','b2','c2'],['v1','v2','v3'],['v100','v101','v102']])
"""
In [14]: df1
Out[14]:
a1 b1 c1
0 a2 b2 c2
1 v1 v2 v3
2 v100 v101 v102
"""
# target dataframe (where "x*" headers will be provided)
df2 = pd.DataFrame(columns=['x1','x2','x3'], data=[['a1','a2','v1'],['a1','a2','v100'],['b1','b2','v2'],['b1','b2','v101'],['c1','c2','v3'],['c1','c2','v102']])
"""
In [16]: df2
Out[16]:
x1 x2 x3
0 a1 a2 v1
1 a1 a2 v100
2 b1 b2 v2
3 b1 b2 v101
4 c1 c2 v3
5 c1 c2 v102
"""
如果我正确理解了您的初始 DataFrame,我可以这样创建它:
import pandas as pd
n = 100
listA = [f'V{x}' for x in range(1,n+1)]
listA.insert(0,("a1"))
listA.insert(1,"a2")
listB = [f'V{x}' for x in range(n+1,2*n+1)]
listB.insert(0,("b1"))
listB.insert(1,"b2")
listC = [f'V{x}' for x in range(2*n+1,3*n+1)]
listC.insert(0,("c1"))
listC.insert(1,"c2")
data = [listA, listB, listC]
df = pd.DataFrame(data).T
现在您创建一个包含三列的空 DataFrame:“x1”、“x2”、“x3”:
newDF = pd.DataFrame( columns=["x1", "x2", "x3"])
然后在 for 循环中添加行,选择元素在原始 DataFrame 中的位置:
for i in range(3):
for j in range(n):
row = [df.iloc[0][i],df.iloc[1][i], df.iloc[j+2][i]]
newDF.loc[len(newDF.index)] = row
希望对你有用。
更新
根据您的更新:
您从 header 列创建一个 row0 :
row0 = pd.DataFrame(list(df1.columns)).T
您更改 row0 和 df1 的列名称:
row0.columns = ["x1","x2","x3"]
df1.columns = ["x1","x2","x3"]
您在 dnew DataFrame 中连接 row0 和 df1:
dnew = pd.concat([row0, df])
您创建 df2 :
df2 = pd.DataFrame(columns=["x1", "x2", "x3"])
for i in range(len(dnew.columns)):
for j in range(len(dnew)-2):
row = [dnew.iloc[0][i],dnew.iloc[1][i], dnew.iloc[j+2][i]]
df2.loc[len(df2)] = row
这是multi-step整形:
(df1.T
.set_index(0, append=True)
.rename_axis(['x1', 'x2'])
.stack()
.droplevel(-1)
.reset_index(name='x3')
)
输出:
x1 x2 x3
0 a1 a2 v1
1 a1 a2 v100
2 b1 b2 v2
3 b1 b2 v101
4 c1 c2 v3
5 c1 c2 v102