1

我有一个带有随机 5 个字母“单词”的 DataFrame。我想使用游戏 Wordle 中的一些标准来过滤它们。

例如,查找满足以下条件的所有单词:

  • 在位置 0 包含“a”
  • 不包含'b'
  • 在位置 2 中包含“c”
  • 在某处包含“d”
  • 不包含'e'

这对应于猜测“abcde”并得到响应:a=green,b=black,c=green,d=yellow,e=black。

我使用 MultiIndex 并为每个字母的存在建立一个列,这感觉效率很低。有更好的方法吗?

import random
import string
import pandas as pd

rand_words = [''.join(random.choice(string.ascii_lowercase) for _ in range(5)) for _ in range(20000)]

tuples = [list(word) for word in rand_words]

index = pd.MultiIndex.from_tuples(tuples, names=["L0", "L1", "L2", "L3", "L4"])

df = pd.DataFrame({"word":rand_words}, index=index)

for ch in string.ascii_lowercase:
    df[ch] = df['word'].map(lambda word: ch in word)

# filter for 'a' and 'c' in positions 0 and 2
# then query for rows that don't contain 'b' or 'e', but do contain 'd'
print(df.xs(('a','c'), level=(0,2), drop_level=False).query('~b & d & ~e')['word'])

输出:

L0  L1  L2  L3  L4
a   d   c   j   q     adcjq
    h   c   d   n     ahcdn
    c   c   d   k     accdk
    s   c   z   d     asczd
4

1 回答 1

0

这是一种使用访问器的方法str,有时使用contains或相反~,有时使用位置[]来获得一个字母并且等于(eq)或不等于( ne)。所以在你的情况下,你可以做

random.seed(1) # for reproductibility
rand_words = [''.join(random.choice(string.ascii_lowercase) 
              for _ in range(5)) for _ in range(20000)]
df = pd.DataFrame({"word":rand_words})

print(
    df.loc[
        df['word'].str[0].eq('a') 
        & ~df['word'].str.contains('b') 
        & df['word'].str[2].eq('c') 
        & df['word'].str.contains('d') & df['word'].str[3].ne('d') 
        & ~df['word'].str.contains('e')
    ]
)

#         word
# 8902   agcsd
# 14816  adcyr

请注意& df['word'].str[3].ne('d')确保 d 不在这个位置的部分,而df['word'].str.contains('d')我理解黄色的意思是存在于这个词中。

于 2022-02-09T21:39:10.893 回答