当前位置: 首页 > 知识库问答 >
问题:

将行值作为列值获取

鲜于允晨
2023-03-14

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

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

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

ID  Price   Net     Range
1   0       300     30
2   700     1159    30
3   2100    2877    47

这里的逻辑是a。将有3个包含TP/VR/TV的列名。所以在ID中,我们有1,2

我尝试了df.filter(regex='TP').stack()。我得到了所有的“TP”栏

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

共有3个答案

尚景焕
2023-03-14

从纯熊猫的角度来看,pivot_wide(参见mozway的答案)在这里可能是最好的,但如果你需要更大的灵活性,你也可以融合和pivot:

import pandas as pd

# recreating your dataframe
df = pd.DataFrame(['AA-24', '0', '700', '2100', '300', '1159', '2877', '30', '30', '47', '10', '5'], 
                  index= ['Num', 'TP1(USD)', 'TP2(USD)', 'TP3(USD)', 'VReal1(USD)', 'VReal2(USD)', 'VReal3(USD)', 'TiV1(EUR)', 'TiV2(EUR)', 'TiV3(EUR)', 'TR', 'TR-Tag']).T

# reshaping the data
(df.melt(id_vars=['Num','TR', 'TR-Tag'])
 .assign(col=lambda x: x['variable'].str[:2], idx=lambda x: x['variable'].str.extract("([0-9])"))
 .pivot(values='value', columns='col', index='idx')
 .rename(columns={'TP': 'Price', 'VR': 'Net', 'Ti': 'Range'})
)

也许令人惊讶的是,这也比宽到长快。对于这种方法,基准测试得出每个回路7.76 ms±841µs。

mozway的wide_to_long方法:

(pd
 .wide_to_long(df.set_axis(df.columns.str.replace(r'\([A-Z]{3}\)$', '', regex=True),
                           axis=1),
               stubnames=['TP', 'VReal', 'TiV'], i='Num', j='ID')
 .rehtml" target="_blank">set_index('ID')
 .drop(columns=['TR', 'TR-Tag'])
 .rename(columns={'TP': 'Price', 'VReal': 'Net', 'TiV': 'Range'})
 )

在我的机器上,每个循环的基准为30.4 ms±3.07 ms。

乌马尔。使用堆栈的H的答案比两者都快:

df1 = df.filter(regex='TP|VR|TV')
df1.columns = df1.columns\
     .str.replace('(\d+)', r' \1' ,regex=True).str.split(' ',expand=True)
df1.stack(1).rename(columns={'TP': 'Price', 'VR': 'Net', 'TV': 'Range'})

每个回路以6.07 ms±156µs的速度运行

如果您不介意额外的导入,sammywemmy的答案使用pyjanitor的pivot_wider提供了速度和优雅的语法。

(df
.select_columns('TP*', 'VR*', 'Ti*')
.pivot_longer(index = None, 
              names_to = ('.value', 'ID'), 
              names_pattern = ('(.+)(\d).+'))
.rename(columns = {'TP':'Price', 'VReal':'Net', 'TiV':'Range'})
)

每回路11.2 ms±229µs的基准

和名称模式方法:

df.pivot_longer(index = None, 
                names_to = ('Price', 'Net', 'Range'), 
                names_pattern = ('TP.*', 'VR.*', 'Ti.*'), 
                ignore_index = False)

是测试批次中速度最快的,每个回路的速度为3.53 ms±95µs。

(值得注意的是,该数据集可能太小,无法考虑速度,在较大的数据集上,顺序可能不同)

南宫龙野
2023-03-14

让我们创建一个多索引,然后使用堆栈

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
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
王高邈
2023-03-14

假设“Num”是唯一标识符,您可以使用pandas.wide\u to\u long:

pd.wide_to_long(df, stubnames=['TP', 'VR', 'TV'], i='Num', j='ID')

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

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'})
 )

输出:

       ID  Price   Net  Range
Num                          
AA-24   1      0   300     30
AA-24   2    700  1159     30
AA-24   3   2100  2877     47
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'})
 )

输出:

       ID  Price   Net  Range
Num                          
AA-24   1      0   300     30
AA-24   2    700  1159     30
AA-24   3   2100  2877     47
 类似资料:
  • 问题内容: 我有一张桌子,我在其中存储合同的交易,如下所示: 用户应该能够选择查询的时间跨度,我要归档的是,如果用户从01/2012-03-2012中选择一个时间跨度,他会得到结果: 您对我有什么建议吗? 最好的问候,r3try 编辑:非常感谢您的答复!当我搜寻我的问题时,我也偶然发现了旋转问题,但是到目前为止,我还没有找到一个可以真正解决我的问题的示例(因为基本上每个示例都为列条目提供了特定的可

  • 问题内容: 我在C#方面非常有经验,但是仍然还是SQL的初学者。 我们有一个使用MSSQL数据库的C#应用​​程序。 我们的应用程序的一部分只是简单地编写一系列预查询,作为报告,通过简单地运行查询并将返回的表粘贴到gridView即可显示该报告。用户正在请求一个新的报表,我不能完全确定仅使用SQL还是可以的,并且需要对返回的数据进行处理才能使其看起来正确。 用户想要的数据(以他们希望的方式呈现)将

  • 问题内容: 我有一个旧的用户信息表(仍在使用中),并且不能更改- 时区/语言/国家等只是名称的示例,它们可以是可变的/除了该列的行上的唯一列表外,没有其他任何有限列表 我需要一个MySQL兼容的SQL查询,该查询将返回- 我已经研究了关于将数据透视表功能窃取到MySQL的关于stackoverflow的各种答案,类似的方法,但是似乎没有一个比从相同表的列的唯一行值使用变量列名别名的情况更好。尽管我

  • 问题内容: 我必须在一行中显示单个人的多个收入,收入类型和雇主名称值。因此,如果“ A”有来自三个不同来源的三个不同的收入, 我需要向他们展示 我既需要“固定列数”(我们知道雇主,收入类型和金额列将要重复多少次)逻辑又需要“动态显示列”(未知这些列要重复的次数) 谢谢。 问题答案: 由于使用的是SQL Server,因此有几种方法可以将数据行转置为列。 聚合函数/ CASE: 您可以将聚合函数与C

  • 问题内容: 我的问题是我有一个这样的表: c1 | c2 | c3 | c4是一个由|分隔的值。 我的最终结果应如下所示: 我该怎么做呢? 谢谢 问题答案: 这就是您可以执行的操作,使用管道将字符串拆分并使用spark函数爆炸数据 输出: 希望这可以帮助!

  • 问题内容: 我正在尝试从SQLite表中提取数据,该表将键值对存储在双列中。例如,用钥匙,,,和,该表将如下所示: 我想执行一个查询,以行作为键,值作为行,每行都给我。像这样: 我唯一能想到的解决方案是每个键的联接: 有一个更好的方法吗? 问题答案: 另一个可用的选项是使用 条件聚合 :