我只有一个.pgn Portable Game Notation,其中包含大量的国际象棋游戏。游戏包含在文件中,如下所示:
[Event "4th Bayern-chI Bank Hofmann"]
[Site "?"]
[Date "2000.10.29"]
[Round "?"]
[White "Carlsen, Magnus"]
[Black "Cordts, Ingo"]
[ECO "A56"]
[WhiteElo "0"]
[BlackElo "2222"]
[Result "0-1"]
1. d4 Nf6 2. c4 c5 3. Nf3 cxd4 4. Nxd4 e5 5. Nb5 d5 6. cxd5 Bc5 7. N5c3 O-O 8. e3 e4 9. h3 Re8 10. g4 Re5 11. Bc4 Nbd7 12. Qb3 Ne8 13. Nd2 Nd6 14. Be2 Qh4 15. Nc4 Nxc4 16. Qxc4 b5 17. Qxb5 Rb8 18. Qa4 Nf6 19. Qc6 Nd7 20. d6 Re6 21. Nxe4 Bb7 22. Qxd7 Bxe4 23. Rh2 Bxd6 24. Bc4 Rd8 25. Qxa7 Bxh2 26. Bxe6 fxe6 27. Qa6 Bf3 28. Bd2 Qxh3 29. Qxe6+ Kh8 30. Qe7 Bc7
0-1
[Event "4th Bayern-chI Bank Hofmann"]
[Site "?"]
[Date "2000.10.30"]
[Round "?"]
[White "Kaiser, Guenter"]
[Black "Carlsen, Magnus"]
[ECO "A46"]
[WhiteElo "0"]
[BlackElo "0"]
[Result "0-1"]
1. d4 Nf6 2. Nf3 d6 3. Nc3 g6 4. e4 Bg7 5. Be2 O-O 6. O-O e5 7. Be3 h6 8. Qd2 Ng4 9. d5 f5 10. exf5 gxf5 11. h3 Nxe3 12. Qxe3 e4 13. Nd4 Qe7 14. Rad1 c5 15. dxc6 bxc6 16. Bc4+ Kh7 17. Nce2 d5 18. Bb3 c5 19. Nb5 d4 20. Qd2 Bb7 21. Nf4 a6 22. Nd5 Qe5 23. Nbc7 Ra7 24. Qa5 Nd7 25. g3 Rc8 26. Nb5 Raa8 27. Nbc7 Bxd5 28. Nxa8 Rxa8 29. Ba4 Be6 30. Kh2 f4 31. Qe1 Nf6 32. Bc6 Rc8 33. Bb7 Rc7 34. Ba8 Bd5 35. Bxd5 Nxd5 36. Qe2 fxg3+
0-1
我想以DataFrame的形式读取此数据,其中列标题只是用引号引起来的字符串左侧的单词,而行值则是用引号引起来的。另一列将包含所有 Action 的字符串。
我对R完全陌生,根本无法弄清楚如何读取尚未采用某种已知格式的文件。
readLines()
看起来很有希望。 最佳答案
试试这个:
pgn <- read.table("your_file.pgn", quote="", sep="\n", stringsAsFactors=FALSE)
# get column names
colnms <- sub("\\[(\\w+).+", "\\1", pgn[1:12,1])
# give columns 11 (the moves) and 12 (redundant results column) nice names
colnms[11] <- "Moves"
colnms[12] <- "Results2"
pgn.df <- data.frame(matrix(sub("\\[\\w+ \\\"(.+)\\\"\\]", "\\1", pgn[,1]),
byrow=TRUE, ncol=12))
names(pgn.df) <- colnms
如您的示例所示,该解决方案假定每个游戏为12行。如果游戏占用的行数不固定,则此解决方案将不起作用。正则表达式行的说明(有关更多信息,请参见
?regex
):sub("\\[(\\w+).+", "\\1", pgn[1:12,1])
在此正则表达式中,我们希望在方括号后的第一个单词。我们必须逃避该括号,因为它是一个元字符。还有其他不使用转义符(\
)的方法,例如,通过将[
放在方括号内来使其成为字符类:sub("[[](\\w+).+", "\\1", pgn[1:12,1])
。括号(捕获组)与
\\1
一起使用。 \\1
是sub
的第二个参数,它表示将原始字符串替换为第一个(仅在这种情况下)捕获组的内容。如果有第二个捕获组,则可以使用\\2
来引用它。捕获组
\\w+
的内容是一个或多个(即+
的意思)字字符(由\\w
表示)。在()
之后,我们想匹配字符串的其余部分,这可以通过一次或多次查找任何字符(即.
的意思)来完成。因此,正则表达式会找到我们捕获的第一个方括号和第一个连续的单词字符块,然后是一个或多个其他字符。
第二个正则表达式:
.+
让我们看一下"\\[\\w+ \\\"(.+)\\\"\\]"
的第一个条目:pgn[,1]
。我们开始时与第一个正则表达式相同,但是这次我们不想捕获第一个单词,我们只想找到其后跟一个空格,然后我们要捕获两组[1] "[Event \"4th Bayern-chI Bank Hofmann\"]"
之间的所有内容。\"
和\
都必须转义,因此我们在捕获组周围有一对"
,该捕获组一次或多次查找任何字符(\\\"
),最后我们得到了一个方括号,该方括号与第一个方括号相同方括号。如果我们不对.+
进行转义,R会认为这是"
的第一个参数的结尾,并且不会将sub
解释为文字引号。在第11行和第12行这样的条目的情况下,不会匹配任何内容,因为这两个行都不以
"
开头,因此,不会替换任何内容。我们只需要将原始字符串全部恢复即可。关于R:如何将PGN读取为数据帧,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30337305/