r - 如何将一串连续的国际象棋移动转换为垂直数据框?

标签 r string dataframe

我有一个象棋游戏的数据框,有两列,如下所示

dd <- data.frame(
  game_id = c(101,102),
  moves = c("1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 Nc6 6.Bc4 e6 7.Be3 Be7","1.e3 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 e5 6.Ndb5 d6")  
)

这里的每一行都是一个单独的游戏,由游戏 ID 唯一标识。移动列按从左到右的顺序包含游戏的所有移动。移动的序列号可以通过每个点“.”之前的数字来识别。每一步都有两个部分;第一部分始终是白棋手的棋步,第二步是黑棋棋手的棋步。这两个部分由一个空格隔开。如上数据所示,连续的两步棋也用一个空格隔开,但是,序号的点与白棋棋步的第一个字符之间没有间隙。游戏中的总步数是任意的,因为有些游戏以几步结束,而另一些则可能有许多步。

问题:正如我们所见,游戏的所有 Action 都存在于数据框的一个单元格中,这不太容易分析。我想将其转换为具有更好结构的数据框,如下所示:

game_id  | move_no | white | black
----------------------------------
    101  | 1       | e4    | c5
    101  | 2       | Nf3   | d6
    101  | 3       | d4    | cxd4
    101  | 4       | Nxd4  | Nf6 

如何在 R 中做到这一点?

最佳答案

我们可以使用正则表达式来绘制移动字符串。这里我使用 stringr::str_match_all 来捕捉 Action 的每个部分。

dd$moves |>
  stringr::str_match_all(r"{(\d+)\.(\S+) (\S+)}") |>
  lapply(function(x) data.frame(move_id=as.numeric(x[,2]), white=x[,3], black=x[,4])) |> 
  Map(cbind.data.frame, game_id=dd$game_id, m=_) |>
  do.call("rbind", args=_)

将返回

   game_id m.move_id m.white m.black
1      101         1      e4      c5
2      101         2     Nf3      d6
3      101         3      d4    cxd4
4      101         4    Nxd4     Nf6
5      101         5     Nc3     Nc6
6      101         6     Bc4      e6
7      101         7     Be3     Be7
8      102         1      e3      c5
9      102         2     Nf3     Nc6

主要部分是正则表达式 r"{(\d+)\.(\S+) (\S+)}" 它找到一个数字后跟一个句点,然后尝试找到两个不包含空格的乐曲名称,它们之间有空格。

关于r - 如何将一串连续的国际象棋移动转换为垂直数据框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72637786/

相关文章:

r - 在R中使用apply或map函数时如何将列名传递给函数?

arrays - R 中的 3 维数组名称

r - 在 randomForest 包的 partialPlot 中使用变量名作为参数

ruby - Ruby 中有点复杂的 eval

python - Pandas 删除一列中的重复项,并仅保留另一列中出现频率最高的行

r - 当列名称存储为串联字符串时选择值

list - 列表中的数据框;添加一个名为数据框的新变量

css - R Shiny : center and resize textInput

c# - 使用正则表达式和 C# 拆分字符串并添加到列表

java - 使用 FART 删除斜杠、反斜杠