Создайте фрейм данных из .pgn (строка строки), используя re - PullRequest
1 голос
/ 28 октября 2019

У меня есть одна .pgn (портативная игровая нотация) большого количества шахматных игр. Игры содержатся в файле следующим образом:

    [Event"FIDE World Cup 2017"]
    [Site "Tbilisi GEO"]
    [Date "2017.09.05"]
    [Round "1.1"]
    [White "Carlsen, Magnus"]
    [Black "Balogun, Oluwafemi"]
    [Result "1-0"]
    [WhiteTitle "GM"]
    [BlackTitle "FM"]
    [WhiteElo "2822"]
    [BlackElo "2255"]
    [ECO "B00"]
    [Opening "King's pawn opening"]
    [WhiteFideId "1503014"]
    [BlackFideId "8501246"]
    [EventDate "2017.09.03"]

    1. e4 d6 2. d4 g6 3. Bc4 Nf6 4. Qe2 Nc6 5. Nf3 Bg7 6. O-O Bg4 7. c3 O-O         
    8. h3 Bxf3 9. Qxf3 e5 10. Rd1 Qe8 11. d5 Ne7 12. Qe2 Nh5 13. Bb5 Qc8 
    14. Na3 a6 15. Ba4 f5 16. Bc2 f4 17. Qg4 Qxg4 18. hxg4 Nf6 19. g5 Nd7 
    20. Nc4 b6 21. b4 h6 22. gxh6 Bxh6 23. g4 Nf6 24. f3 Bg5 25. Kg2 Kg7 
    26. a4 Bh4 27. Bd2 g5 28. Rh1 Ng6 29. Kf1 Rh8 30. Ke2 Bg3 31. a5 b5 32. 
    Na3 Ne7 33. c4 c6 34. dxc6 Nxc6 35. Bc3 Rxh1 36. Rxh1 bxc4 37. Nxc4 Rb8 
    38. Nxd6 Kg6 39. Nf5 1-0

    [Event "FIDE World Cup 2018"]    
    etc...

Я хотел бы создать фрейм данных с этими данными, где заголовки столбцов - это слова, повторяющиеся в скобках, такие как «Событие» или «Сайт». и данные в кавычках. Кроме того, я хотел бы, конечно, включить ходы, которые не заключены ни в кавычки, ни в скобки ...

Я думаю, что я мог бы использовать модуль re, чтобы сначала построить словарь, а затем преобразовать словарь в данные. кадр, но я не способен сделать это. Не могли бы вы помочь мне?

Nested_dict = { 
  "Game1": {"Event" : "FIDE World Cup 2017" , "Site " : "Tbilisi GEO" , "moves": "1. e4 d6"}
  "Game2": {"Event" : "FIDE World Cup 2018" , "Site " : "Astana GEO" , "moves": "1. e4 e5"}
}

Я сделал все, чтобы получить все «значения» словаря, но не могу получить «ключи»:

import re

with open('lichess_game.pgn', 'r') as in_file:
    stripped = (line.strip() for line in in_file)
    lines = ((line.split(",") for line in stripped if line))
    for line in lines:
        stripped=str(line)
        stripped = (stripped.replace("]",""))
        stripped=stripped.replace("[","")
        values=str(re.findall(r'["](.*?)["]',stripped)) #Is there someting like re.finall(not(condition)? I mean, find everthing that is not inside this condition
        values = (values.replace("]",'"')) #Could I replace two diferent characters at the same time?
        values=values.replace("[",'"')
        key=stripped.replace((values),"") #this is me trying the get the key from the string minus the values....
        print(values) #Right!
        print(key)    #Nope

В итоговой таблице фрейма данных будут все игры в строках, а в каждом столбце информация о каждой игре, например, в столбце 1 будет «Событие», а в первой строке «Чемпионат мира по футболу FIDE 2017»

Event               Site    Date       Round White           Black  
FIDE World Cup 2017 Tbilisi 2017.09.05 1.1   Carlsen, Magnus Balogun, Oluwafemi

Большое спасибо за вашу помощь !!

1 Ответ

0 голосов
/ 29 октября 2019

Я использую пустую строку и переменную moves, чтобы определить, является ли это началом строк с ходами или началом линий в новой игре.

Для игры я использую [1:-1], чтобы удалить [ ] и позже" ". Я использую split(' ', 1), чтобы разбить текст внутри [ ] на два элемента, которые я использую в качестве ключа и значения в dict.

Для ходов я сохраняю их в списке, и когда начинается новая игра, я соединяю их и помещаюв словаре. Когда начинается новая игра, я очищаю команду dict для новой строки и список для новых ходов.

Я использую модуль json только для отображения словаря в более читабельной форме. Не нужно работать с данными.

text = '''[Event "FIDE World Cup 2017"]
    [Site "Tbilisi GEO"]
    [Date "2017.09.05"]
    [Round "1.1"]
    [White "Carlsen, Magnus"]
    [Black "Balogun, Oluwafemi"]
    [Result "1-0"]
    [WhiteTitle "GM"]
    [BlackTitle "FM"]
    [WhiteElo "2822"]
    [BlackElo "2255"]
    [ECO "B00"]
    [Opening "King's pawn opening"]
    [WhiteFideId "1503014"]
    [BlackFideId "8501246"]
    [EventDate "2017.09.03"]

    1. e4 d6 2. d4 g6 3. Bc4 Nf6 4. Qe2 Nc6 5. Nf3 Bg7 6. O-O Bg4 7. c3 O-O         
    8. h3 Bxf3 9. Qxf3 e5 10. Rd1 Qe8 11. d5 Ne7 12. Qe2 Nh5 13. Bb5 Qc8 
    14. Na3 a6 15. Ba4 f5 16. Bc2 f4 17. Qg4 Qxg4 18. hxg4 Nf6 19. g5 Nd7 
    20. Nc4 b6 21. b4 h6 22. gxh6 Bxh6 23. g4 Nf6 24. f3 Bg5 25. Kg2 Kg7 
    26. a4 Bh4 27. Bd2 g5 28. Rh1 Ng6 29. Kf1 Rh8 30. Ke2 Bg3 31. a5 b5 32. 
    Na3 Ne7 33. c4 c6 34. dxc6 Nxc6 35. Bc3 Rxh1 36. Rxh1 bxc4 37. Nxc4 Rb8 
    38. Nxd6 Kg6 39. Nf5 1-0

[Event "FIDE World Cup 2017"]
    [Site "Tbilisi GEO"]
    [Date "2017.09.05"]
    [Round "1.1"]
    [White "Carlsen, Magnus"]
    [Black "Balogun, Oluwafemi"]
    [Result "1-0"]
    [WhiteTitle "GM"]
    [BlackTitle "FM"]
    [WhiteElo "2822"]
    [BlackElo "2255"]
    [ECO "B00"]
    [Opening "King's pawn opening"]
    [WhiteFideId "1503014"]
    [BlackFideId "8501246"]
    [EventDate "2017.09.03"]

    1. e4 d6 2. d4 g6 3. Bc4 Nf6 4. Qe2 Nc6 5. Nf3 Bg7 6. O-O Bg4 7. c3 O-O         
    8. h3 Bxf3 9. Qxf3 e5 10. Rd1 Qe8 11. d5 Ne7 12. Qe2 Nh5 13. Bb5 Qc8 
    14. Na3 a6 15. Ba4 f5 16. Bc2 f4 17. Qg4 Qxg4 18. hxg4 Nf6 19. g5 Nd7 
    20. Nc4 b6 21. b4 h6 22. gxh6 Bxh6 23. g4 Nf6 24. f3 Bg5 25. Kg2 Kg7 
    26. a4 Bh4 27. Bd2 g5 28. Rh1 Ng6 29. Kf1 Rh8 30. Ke2 Bg3 31. a5 b5 32. 
    Na3 Ne7 33. c4 c6 34. dxc6 Nxc6 35. Bc3 Rxh1 36. Rxh1 bxc4 37. Nxc4 Rb8 
    38. Nxd6 Kg6 39. Nf5 1-0    
    '''

all_rows = dict()

# create dict/list for first game
row = dict()
moves = False
moves_lines = list()
game = 1

for line in text.split('\n'):
    line = line.strip()
    if line:
        if moves:
            moves_lines.append(line)
        elif line.startswith('['):
            line = line[1:-1]
            parts = line.split(' ', 1)
            parts[1] = parts[1][1:-1]
            row[parts[0]] = parts[1]
    else:
        # if empty line then it is beginning of moves or beginning of new game
        if not moves:
            # start lines with moves
            moves = True
        else:
            # end of lines with moves - so it is time to add it to dict
            row['moves'] = ' '.join(moves_lines)
            all_rows['Game{}'.format(game)] = row

            # create dict/list for next game
            row = dict()
            moves = False
            moves_lines = list()
            game += 1

# after loop there can be last row to fill            
if row: 
   row['moves'] = ' '.join(moves_lines)
   all_rows['Game{}'.format(game)] = row

import json
print(json.dumps(all_rows, indent=2))

Результат (отформатирован json)

{
  "Game1": {
    "Event": "FIDE World Cup 2017",
    "Site": "Tbilisi GEO",
    "Date": "2017.09.05",
    "Round": "1.1",
    "White": "Carlsen, Magnus",
    "Black": "Balogun, Oluwafemi",
    "Result": "1-0",
    "WhiteTitle": "GM",
    "BlackTitle": "FM",
    "WhiteElo": "2822",
    "BlackElo": "2255",
    "ECO": "B00",
    "Opening": "King's pawn opening",
    "WhiteFideId": "1503014",
    "BlackFideId": "8501246",
    "EventDate": "2017.09.03",
    "moves": "1. e4 d6 2. d4 g6 3. Bc4 Nf6 4. Qe2 Nc6 5. Nf3 Bg7 6. O-O Bg4 7. c3 O-O 8. h3 Bxf3 9. Qxf3 e5 10. Rd1 Qe8 11. d5 Ne7 12. Qe2 Nh5 13. Bb5 Qc8 14. Na3 a6 15. Ba4 f5 16. Bc2 f4 17. Qg4 Qxg4 18. hxg4 Nf6 19. g5 Nd7 20. Nc4 b6 21. b4 h6 22. gxh6 Bxh6 23. g4 Nf6 24. f3 Bg5 25. Kg2 Kg7 26. a4 Bh4 27. Bd2 g5 28. Rh1 Ng6 29. Kf1 Rh8 30. Ke2 Bg3 31. a5 b5 32. Na3 Ne7 33. c4 c6 34. dxc6 Nxc6 35. Bc3 Rxh1 36. Rxh1 bxc4 37. Nxc4 Rb8 38. Nxd6 Kg6 39. Nf5 1-0"
  },
  "Game2": {
    "Event": "FIDE World Cup 2017",
    "Site": "Tbilisi GEO",
    "Date": "2017.09.05",
    "Round": "1.1",
    "White": "Carlsen, Magnus",
    "Black": "Balogun, Oluwafemi",
    "Result": "1-0",
    "WhiteTitle": "GM",
    "BlackTitle": "FM",
    "WhiteElo": "2822",
    "BlackElo": "2255",
    "ECO": "B00",
    "Opening": "King's pawn opening",
    "WhiteFideId": "1503014",
    "BlackFideId": "8501246",
    "EventDate": "2017.09.03",
    "moves": "1. e4 d6 2. d4 g6 3. Bc4 Nf6 4. Qe2 Nc6 5. Nf3 Bg7 6. O-O Bg4 7. c3 O-O 8. h3 Bxf3 9. Qxf3 e5 10. Rd1 Qe8 11. d5 Ne7 12. Qe2 Nh5 13. Bb5 Qc8 14. Na3 a6 15. Ba4 f5 16. Bc2 f4 17. Qg4 Qxg4 18. hxg4 Nf6 19. g5 Nd7 20. Nc4 b6 21. b4 h6 22. gxh6 Bxh6 23. g4 Nf6 24. f3 Bg5 25. Kg2 Kg7 26. a4 Bh4 27. Bd2 g5 28. Rh1 Ng6 29. Kf1 Rh8 30. Ke2 Bg3 31. a5 b5 32. Na3 Ne7 33. c4 c6 34. dxc6 Nxc6 35. Bc3 Rxh1 36. Rxh1 bxc4 37. Nxc4 Rb8 38. Nxd6 Kg6 39. Nf5 1-0"
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...