【问题标题】:Using column name as a new attribute in pandas在 pandas 中使用列名作为新属性
【发布时间】:2018-01-23 18:37:18
【问题描述】:

我有以下数据结构

Date         Agric  Food 
01/01/1990    1.3   0.9  
01/02/1990    1.2   0.9 

我想把它转换成格式

Date        Sector  Beta
01/01/1990  Agric   1.3
01/02/1990  Agric   1.2
01/01/1990  Food    0.9
01/02/1990  Food    0.9

虽然我确信我可以以复杂的方式做到这一点,但有没有办法在几行代码中做到这一点?

【问题讨论】:

    标签: python pandas reshape


    【解决方案1】:

    使用pd.DataFrame.melt

    df.melt('Date', var_name='Sector', value_name='Beta')
    
             Date Sector  Beta
    0  01/01/1990  Agric   1.3
    1  01/02/1990  Agric   1.2
    2  01/01/1990   Food   0.9
    3  01/02/1990   Food   0.9
    

    【讨论】:

    • 快速提问:您使用了 df.melt,但您添加的链接是 pd.melt(),它们是否等效?
    • 它们是等价的。在pandas 0.20 然后将pd.melt 变成pd.DataFrame 方法。我混淆了链接。我修复了链接,但它们是等效的。
    【解决方案2】:

    使用set_indexstack

    df.set_index('Date').rename_axis('Sector',axis=1).stack()\
      .reset_index(name='Beta')
    

    输出:

             Date Sector  Beta
    0  01/01/1990  Agric   1.3
    1  01/01/1990   Food   0.9
    2  01/02/1990  Agric   1.2
    3  01/02/1990   Food   0.9
    

    【讨论】:

    • stack~:)
    【解决方案3】:

    或者你可以使用lreshape

    df=pd.lreshape(df2, {'Date': ["Date","Date"], 'Beta': ['Agric', 'Food']})
    df['Sector']=sorted(df2.columns.tolist()[1:3]*2)
    
       Out[654]: 
             Date  Beta Sector
    0  01/01/1990   1.3  Agric
    1  01/02/1990   1.2  Agric
    2  01/01/1990   0.9   Food
    3  01/02/1990   0.9   Food
    

    如果你有 48 列

    df=pd.lreshape(df2, {'Date':['Date']*2, 'Beta': df2.columns.tolist()[1:3]})
    df['Sector']=sorted(df2.columns.tolist()[1:3]*2)
    

    同样对于列 Sector ,由

    创建它更安全
    import itertools
    list(itertools.chain.from_iterable(itertools.repeat(x, 2) for x in df2.columns.tolist()[1:3]))
    

    编辑原因 lreshap 未记录(根据@Ted Petrou 如果可能,最好使用可用的 DataFrame 方法,如果没有可用的方法,请使用记录的函数。pandas 一直在寻求改进其 API 并调用像 lreshape 这样无证的、旧的和实验性的函数是没有根据的。此外,这个问题是一个非常简单的融化或堆栈用例。这是一个不好的先例,让熊猫新手来到 Stack Overflow 并使用 lreshape 找到赞成的答案.

    另外,如果你想了解更多,可以到github查看

    下面是使用pd.wide_to_long的方法

    dict1 = {'Agric':'A_Agric','Food':'A_Food'}
    df2 = df.rename(columns=dict1)
    pd.wide_to_long(df2.reset_index(),['A'],i='Date',j='Sector',sep='_',suffix='.').reset_index().drop('index',axis=1).rename(columns={'A':'Beta '})
    
    Out[2149]: 
             Date Sector  Beta 
    0  01/01/1990  Agric    1.3
    1  01/02/1990  Agric    1.2
    2  01/01/1990   Food    0.9
    3  01/02/1990   Food    0.9
    

    【讨论】:

    • 我唯一关心的是我在真实数据中有 48 列。 :)
    • 那么,你可以用df.columns.tolist(),一秒钟,我会编辑它
    • @Lost1 已编辑~
    • 如果可能,最好使用可用的 DataFrame 方法,如果没有可用的方法,则使用文档化的函数。 pandas 一直在寻求改进其 API 并调用未记录的、旧的和实验性的函数,如 lreshape,因为任何事情都是没有根据的。此外,这个问题对于熔体或堆叠来说是一个非常简单的用例。这是一个不好的先例,让那些刚接触 pandas 的人来到 Stack Overflow 并通过lreshape 找到被赞成的答案。不幸的是,堆栈溢出以同样的方式鼓励了糟糕的.ix 索引运算符的传播和使用。
    • @TedPetrou 有点同意顺便说一句,如果你能在 github 上发布你提到的关于lreshape 的问题将不胜感激
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 2015-10-23
    • 2016-12-02
    • 1970-01-01
    相关资源
    最近更新 更多