【问题标题】:Pandas: Generate new columns by old one熊猫:由旧列生成新列
【发布时间】:2022-01-09 21:07:49
【问题描述】:

我有一个数据框,其中包含一列来自国际象棋的FEN notations,我想拆分此列,格式为

2kr2nr/pp5p/3bpppP/1b1p4/8/1BB1P3/PP3PP1/R3K2R

分成 64 列 a1 到 h8,包含其中的字母,如果为空,则为 -

功能有点复杂,应该不是问题的问题,但我问自己的是:

在 pandas 数据框中生成 64 列的最佳方法是什么?

我知道可以运行函数的应用函数之类的东西,但我只看到一列。 有没有一种聪明的方法可以一次对所有 64 列执行此操作?


对于那些想知道我所做的确切事情的人:

FEN 由八个由 / 分隔的子字符串组成,它们是第 8 到 1 行(是的,以相反的顺序)。 每个部分都说明了该行中八个字段的外观。如果有一个数字,它会告诉你有多少个空字段(从左到右),如果是一个字母,它会告诉你后面是哪一个。

所以在我上面的例子中,a8 和 b8 是空的(因为 2),然后有一个“k”,“r”,e8 和 h8 上还有两个空,然后是“n”和“ r"。一行中的 8 表示该行为空。

所以一个例子是: 输入:

2kr2nr/pp5p/3bpppP/1b1p4/8/1BB1P3/PP3PP1/R3K2R

输出:

a8 -
b8 -
c8 k
d8 r
e8 -
f8 -
g8 n
h8 r
a7 p
b7 p
c7 -
d7 -
e7 -
f7 -
g7 -
h7 p
...
a1 R
b2 -
c1 -
d1 -
e1 K
f1 -
g1 -
h1 R

【问题讨论】:

  • 为什么要这样解析FEN?
  • 机器学习
  • 好的。我正在考虑使用像 python-chess 这样的工具来为您完成工作

标签: python pandas dataframe chess


【解决方案1】:

您可以使用自定义函数。例如:

def fen2list(s):
    from itertools import chain, product
    l = list(chain.from_iterable('-'*int(c)
                                 if c.isdigit() else c
                                 for c in s if c != '/'))
    
    cols = list(map(''.join, product('abcdefgh', '87654321')))
    
    return pd.Series(l, index=cols)

例子:

fen2list('2kr2nr/pp5p/3bpppP/1b1p4/8/1BB1P3/PP3PP1/R3K2R')

输出:

a8    -
a7    -
a6    k
a5    r
a4    -
     ..
h5    -
h4    K
h3    -
h2    -
h1    R

如果您有一个包含一列 FEN 字符串的 DataFrame,您可以将 apply 与您的自定义函数一起使用:

df['FEN'].apply(fen2list)

【讨论】:

  • 你能帮我调试一下我的专栏吗? :)
  • 有什么问题? (我在打电话,屏幕太小了!)
  • 根据 OP 的解释,这应该是product('hgfedcba', '12345678')。顺便说一句,list 没用,字符串是可迭代的;)
  • 您应该编辑您的问题以添加一个最小的可重现示例以明确显示此输入和输出
  • @DORpapst 好的,只需将产品更改为product('abcdefgh', '87654321')
【解决方案2】:

假设以下数据框:

import pandas as pd

# https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation#Examples
data = ['rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR',
        'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR',
        'rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR',
        'rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R']
df = pd.DataFrame({'FEN': data})
print(df)

# Output
                                                 FEN
0        rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
1      rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR
2    rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR
3  rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R

创建一个解码函数(改编自@TimRoberts answer

from itertools import product

cells = [f"{l}{n}" for n, l in product('87654321', 'ABCDEFGH')]

def decode_fen(fen):
    board = []
    for c in fen:
        if c == '/':
            continue
        elif c.isdigit():
            board.extend('-' * int(c))
        elif c.isalpha():
            board.append(c)
        else:
            board.append('-')
    return pd.Series(board, index=cells)

创建您的列:

fen = df['FEN'].apply(decode_fen)

df = df.join(fen)

输出:

>>> df
                                                 FEN A8 B8 C8 D8 E8 F8 G8 H8 A7 B7 C7 D7 E7 F7 G7 H7 A6 B6 C6 D6 E6 F6 G6 H6 A5 B5 C5 D5 E5 F5 G5 H5 A4 B4 C4 D4 E4 F4 G4 H4 A3 B3 C3 D3 E3 F3 G3 H3 A2 B2 C2 D2 E2 F2 G2 H2 A1 B1 C1 D1 E1 F1 G1 H1
0        rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR  r  n  b  q  k  b  n  r  p  p  p  p  p  p  p  p  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  P  P  P  P  P  P  P  P  R  N  B  Q  K  B  N  R
1      rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR  r  n  b  q  k  b  n  r  p  p  p  p  p  p  p  p  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  P  -  -  -  -  -  -  -  -  -  -  -  P  P  P  P  -  P  P  P  R  N  B  Q  K  B  N  R
2    rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR  r  n  b  q  k  b  n  r  p  p  -  p  p  p  p  p  -  -  -  -  -  -  -  -  -  -  p  -  -  -  -  -  -  -  -  -  P  -  -  -  -  -  -  -  -  -  -  -  P  P  P  P  -  P  P  P  R  N  B  Q  K  B  N  R
3  rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R  r  n  b  q  k  b  n  r  p  p  -  p  p  p  p  p  -  -  -  -  -  -  -  -  -  -  p  -  -  -  -  -  -  -  -  -  P  -  -  -  -  -  -  -  -  N  -  -  P  P  P  P  -  P  P  P  R  N  B  Q  K  B  -  R

【讨论】:

  • 似乎工作正常,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-14
  • 2022-10-12
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 2022-12-10
相关资源
最近更新 更多