获取行值作为列值

moy*_*oys 9 python pandas

我有一个单行数据框,如下所示

Num     TP1(USD)    TP2(USD)    TP3(USD)    VReal1(USD)     VReal2(USD)     VReal3(USD)     TiV1 (EUR)  TiV2 (EUR)  TiV3 (EUR)  TR  TR-Tag
AA-24   0       700     2100    300     1159    2877    30       30     47      10  5
Run Code Online (Sandbox Code Playgroud)

我想要得到一个像下面这样的数据框

ID  Price   Net     Range
1   0       300     30
2   700     1159    30
3   2100    2877    47
Run Code Online (Sandbox Code Playgroud)

这里的逻辑是a. 将有 3 个包含 TP/VR/TV 的列名称。因此,在 ID 中,我们有 1、2 和 3(这些可以通过从列名中提取值或仅使用范围来填充来生成)b。TP1 值进入“价格”列的第一行,TP2 值进入“价格”列的第二行,依此类推 c.VR 和电视也是如此。这些值进入“净值”和“范围”列 d。列“Num”、“TR”和“TR=Tag”与结果无关。

我试过df.filter(regex='TP').stack()。我得到了所有“TP”列,并且可以通过索引([0],[1],[2])访问各个值。我无法将它们全部直接放入一个列中。

我还想知道是否有更简单的方法可以做到这一点。

moz*_*way 12

假设'Num'是唯一标识符,您可以使用pandas.wide_to_long

pd.wide_to_long(df, stubnames=['TP', 'VR', 'TV'], i='Num', j='ID')
Run Code Online (Sandbox Code Playgroud)

或者,对于更接近您的输出:

out = (pd
 .wide_to_long(df, stubnames=['TP', 'VR', 'TV'], i='Num', j='ID')
 .reset_index('ID')
 .drop(columns=['TR', 'TR-Tag'])
 .rename(columns={'TP': 'Price', 'VR': 'Net', 'TV': 'Range'})
 )
Run Code Online (Sandbox Code Playgroud)

输出:

       ID  Price   Net  Range
Num                          
AA-24   1      0   300     30
AA-24   2    700  1159     30
AA-24   3   2100  2877     47
Run Code Online (Sandbox Code Playgroud)
更新的答案
out = (pd
 .wide_to_long(df.set_axis(df.columns.str.replace(r'\(USD\)$', '', regex=True),
                           axis=1),
               stubnames=['TP', 'VReal', 'TiV'], i='Num', j='ID')
 .reset_index('ID')
 .drop(columns=['TR', 'TR-Tag'])
 .rename(columns={'TP': 'Price', 'VReal': 'Net', 'TiV': 'Range'})
 )
Run Code Online (Sandbox Code Playgroud)

输出:

       ID  Price   Net  Range
Num                          
AA-24   1      0   300     30
AA-24   2    700  1159     30
AA-24   3   2100  2877     47
Run Code Online (Sandbox Code Playgroud)


Dat*_*ice 5

让我们创建一个Multiindex然后使用.stack

df1 = df.filter(regex='TP|VR|TV')
#i couldn't figure out to split by 
#word\number without creating an additional whitespace split.
df1.columns = df1.columns\
     .str.replace('(\d+)', r' \1' ,regex=True).str.split(' ',expand=True)

#or more succinctly.
df1.columns = pd.MultiIndex.from_frame(df1.columns.str.extract('(\D+)(\d+)'))   

print(df1)

  TP              VR              TV
   1    2     3    1     2     3   1   2   3
0  0  700  2100  300  1159  2877  30  30  47
Run Code Online (Sandbox Code Playgroud)
df1.stack(1).rename(columns={'TP': 'Price', 'VR': 'Net', 'TV': 'Range'})
    
     Price  Range   Net
0 1      0     30   300
  2    700     30  1159
  3   2100     47  2877
Run Code Online (Sandbox Code Playgroud)