Как свести столбцы фрейма данных Pandas в индекс самого внутреннего уровня без использования df.iterrows()?

avatar
Sherman Chen
8 августа 2021 в 20:56
142
3
0

Исходный файл .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(), поскольку при работе с большими данными он будет работать очень медленно.

Как я могу повернуть столбцы Pandas DataFrame в индекс самого внутреннего уровня и получить результат следующим образом, без использования df.iterrows(), тогда?

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
Источник

Ответы (3)

avatar
Henry Ecker
8 августа 2021 в 21:14
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
Sherman Chen
9 августа 2021 в 01:48
0

@Henry Ecker, stack(), to_string('output.txt') — лаконично, мощно и красиво!

Sherman Chen
12 августа 2021 в 01:53
0

Генри Экер, я просто обнаружил, что если я использую 'to_string' и если ячейка содержит длинное предложение, то длинное предложение усекается.

Henry Ecker
12 августа 2021 в 02:06
1

Маловероятно, что to_string будет вести себя таким образом. max_colwidth по умолчанию неограничен. Я также только что протестировал его со столбцом строк длиной 10 000 символов, и он распечатался правильно. Вы можете перепроверить свои исходные данные или задать новый вопрос с помощью MRE, который можно использовать для воспроизведения этой новой проблемы с усечением.

Sherman Chen
12 августа 2021 в 03:24
0

Генри Эккер, конечно. Я задал новый вопрос

avatar
maanas
8 августа 2021 в 21:14
1

Вы можете использовать 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)
Sherman Chen
12 августа 2021 в 01:59
0

maanas, я просто обнаружил, что если я использую 'df.apply(axis=1)' и если ячейка содержит длинное предложение, то длинное предложение усекается.

avatar
Cimbali
8 августа 2021 в 21:13
3

С помощью 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
Sherman Chen
12 августа 2021 в 01:56
0

Cimbali, я просто обнаружил, что если я использую «df.agg», «str.cat» и если ячейка содержит длинное предложение, то длинное предложение усекается.

Cimbali
12 августа 2021 в 07:11
1

Я полагаю, это тот же механизм, что и в ответе @HenryEcker. Ваш новый вопрос должен решить эту проблему.