【问题标题】:How to Pivot Columns of a Pandas DataFrame into Inner-most Level Index without Using df.iterrows()?如何在不使用 df.iterrows() 的情况下将 Pandas DataFrame 的列转换为最内层索引?
【发布时间】:2021-08-08 20:56:55
【问题描述】:

原始 .csv 文件 -

#,Name,Type 1,Type 2,HP,Attack,Defense,Sp. Atk,Sp. Def,Speed,Generation,Legendary
1,Bulbasaur,Grass,Poison,45,49,49,65,65,45,1,FALSE
2,Ivysaur,Grass,Poison,60,62,63,80,80,60,1,FALSE
3,Venusaur,Grass,Poison,80,82,83,100,100,80,1,FALSE

我的 Python 代码使用 df.iterrows() -

import pandas as pd
import os

df = pd.read_csv('pokemon_data.csv')
with open('output.txt', 'w') as f:
    for index, row in df.iterrows():
        row_i = str(index) + str(row)
        f.write(row_i)

我了解到我们应该避免使用 df.iterrow(),因为它在处理大数据时会变得非常慢。

如何不使用 df.iterrows() 将 Pandas DataFrame 的列转入最内层索引,并获得如下结果?

0 #                     1
Name          Bulbasaur
Type 1            Grass
Type 2           Poison
HP                   45
Attack               49
Defense              49
Sp. Atk              65
Sp. Def              65
Speed                45
Generation            1
Legendary         False

1 #                   2
Name          Ivysaur
Type 1          Grass
Type 2         Poison
HP                 60
Attack             62
Defense            63
Sp. Atk            80
Sp. Def            80
Speed              60
Generation          1
Legendary       False

2 #                    3
Name          Venusaur
Type 1           Grass
Type 2          Poison
HP                  80
Attack              82
Defense             83
Sp. Atk            100
Sp. Def            100
Speed               80
Generation           1
Legendary        False

【问题讨论】:

    标签: python pandas dataframe loops row


    【解决方案1】:

    使用str(),您可以获得每一行的字符串表示,然后将它们与.str.cat 连接在一起:

    >>> print(df.agg(str, axis='columns').str.cat(sep='\n\n'))
    #                     1
    Name          Bulbasaur
    Type 1            Grass
    Type 2           Poison
    HP                   45
    Attack               49
    Defense              49
    Sp. Atk              65
    Sp. Def              65
    Speed                45
    Generation            1
    Legendary         False
    Name: 0, dtype: object
    
    #                   2
    Name          Ivysaur
    Type 1          Grass
    Type 2         Poison
    HP                 60
    Attack             62
    Defense            63
    Sp. Atk            80
    Sp. Def            80
    Speed              60
    Generation          1
    Legendary       False
    Name: 1, dtype: object
    
    #                    3
    Name          Venusaur
    Type 1           Grass
    Type 2          Poison
    HP                  80
    Attack              82
    Defense             83
    Sp. Atk            100
    Sp. Def            100
    Speed               80
    Generation           1
    Legendary        False
    Name: 2, dtype: object
    

    如果你想保留索引号,你可以使用reset_index(),然后调整字符串表示

    >>> print(df.reset_index().agg(str, axis='columns').str.replace(r'^index\s*', '', regex=True).str.cat(sep='\n\n'))
    0
    #                     1
    Name          Bulbasaur
    Type 1            Grass
    Type 2           Poison
    HP                   45
    Attack               49
    Defense              49
    Sp. Atk              65
    Sp. Def              65
    Speed                45
    Generation            1
    Legendary         False
    

    【讨论】:

    • Cimbali,我只是发现如果我使用'df.agg','str.cat',并且如果一个单元格包含一个长句,那么长句会被截断。
    • 我想这与@HenryEcker's answer的机制相同。您的新问题应该可以解决这个问题。
    【解决方案2】:

    我们可以试试stack + to_string:

    df.stack().to_string('output.txt')
    

    output.txt:

    0  #                     1
       Name          Bulbasaur
       Type 1            Grass
       Type 2           Poison
       HP                   45
       Attack               49
       Defense              49
       Sp. Atk              65
       Sp. Def              65
       Speed                45
       Generation            1
       Legendary         False
    1  #                     2
       Name            Ivysaur
       Type 1            Grass
       Type 2           Poison
       HP                   60
       Attack               62
       Defense              63
       Sp. Atk              80
       Sp. Def              80
       Speed                60
       Generation            1
       Legendary         False
    2  #                     3
       Name           Venusaur
       Type 1            Grass
       Type 2           Poison
       HP                   80
       Attack               82
       Defense              83
       Sp. Atk             100
       Sp. Def             100
       Speed                80
       Generation            1
       Legendary         False
    

    【讨论】:

    • @Henry Ecker, stack(), to_string('output.txt') - 简洁、强大、美观!
    • Henry Ecker,我只是发现如果我使用'to_string',并且如果一个单元格包含一个长句子,那么长句子就会被截断。
    • to_string 似乎不太可能这样做。 max_colwidth 默认是无限制的。我还刚刚用一列 10,000 个字符长的字符串对其进行了测试,并且打印正确。您可以考虑仔细检查您的源数据,或者询问new questionMRE,这可用于重现这个新的截断问题。
    • 亨利·埃克,当然。我问过a new question
    【解决方案3】:

    你可以使用df.apply(axis=1):

    import pandas as pd
    import os
    
    df = pd.read_csv('pokemon_data.csv')
    with open('output.txt', 'w') as f:
        def write_pokemon(pokemon):
            f.write('\n\n')
            f.write(pokemon.to_string())
    
        df.apply(write_pokemon, axis=1)
    

    【讨论】:

    • maanas,我只是发现如果我使用'df.apply(axis=1)',并且如果一个单元格包含一个长句子,那么长句子就会被截断。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-07
    • 2016-02-29
    • 2013-07-17
    • 2020-06-22
    • 1970-01-01
    • 2023-01-04
    • 2020-06-15
    相关资源
    最近更新 更多