Pandas带筛选的列操作:字符串字符转换问题求助
解决Pandas DataFrame中卡片字符转换问题
问题描述
现有如下Pandas DataFrame:
ID Cards ... opp cards1 0 flop850262436159b10 ('3h', 'tc', '5s') ... 0.000000 10 1 flop850262436159b10 ('3h', 'tc', '5s') ... 0.533690 10 2 flop850262436159b10 ('3h', 'tc', '5s') ... 0.021292 10 3 flop850262436159b10 ('3h', 'tc', '5s') ... 0.022805 10 4 flop850262436159b10 ('3h', 'tc', '5s') ... 0.999691 10 ... ... ... ... ... 749995 flop573952955203b10 ('ts', '2c', 'jd') ... 0.162980 10 749996 flop573952955203b10 ('ts', '2c', 'jd') ... 0.541003 10 749997 flop573952955203b10 ('ts', '2c', 'jd') ... 0.341836 10 749998 flop573952955203b10 ('ts', '2c', 'jd') ... 0.219956 10 749999 flop573952955203b10 ('ts', '2c', 'jd') ... 0.363605 10
需求:提取Cards列中每个卡片的第一个字符(比如('3h', 'tc', '5s')里的3、t、5),若该字符为字母(如t、j),则转换为对应整数(例如t转为10),否则保持原数字字符。
原尝试代码(无效):
df = pd.read_csv('path', sep=";") if (df['cards'].astype(str).str[0] =="t").any() == True: df['cards1'] = 10 else: df['cards1'] = df['cards'].astype(str).str[0]
问题根源:any()会判断整个列是否存在符合条件的行,只要有一行满足,就会把整个cards1列设为10,无法实现逐行判断。
解决方案
方法1:解析元组+自定义函数处理
先将Cards列的字符串形式元组转为实际元组,再逐个处理每个卡片的第一个字符:
import pandas as pd # 读取数据 df = pd.read_csv('path', sep=";") # 定义字符映射字典,可根据需求扩展(如j=11、q=12等) char_map = {'t': 10, 'j': 11, 'q': 12, 'k':13, 'a':1} def process_cards(cards_str): # 转换字符串元组为实际元组 cards = eval(cards_str) processed = [] for card in cards: first_char = card[0].lower() # 匹配映射表则替换为数字,否则保留原字符 processed.append(char_map.get(first_char, card[0])) return processed # 生成处理后的列,若仅需第一个卡片的结果,可改为process_cards(x)[0] df['cards1'] = df['Cards'].apply(process_cards)
方法2:正则表达式提取+映射
无需解析元组,直接用正则匹配所有卡片的第一个字符再替换:
import pandas as pd import re df = pd.read_csv('path', sep=";") char_map = {'t': '10', 'j': '11', 'q': '12', 'k':'13', 'a':'1'} def get_processed_chars(cards_str): # 提取所有卡片的第一个字符 chars = re.findall(r"'(\w)", cards_str) # 替换字母为对应数字 return [char_map.get(c.lower(), c) for c in chars] df['cards1'] = df['Cards'].apply(get_processed_chars)
方法3:针对单卡片的简化处理
若仅需提取Cards列中第一个卡片的第一个字符并转换:
import pandas as pd import numpy as np df = pd.read_csv('path', sep=";") # 提取第一个卡片的第一个字符 first_chars = df['Cards'].str.extract(r"'(\w)").squeeze() # 逐行判断替换 df['cards1'] = np.where(first_chars.str.lower() == 't', 10, np.where(first_chars.str.lower() == 'j', 11, first_chars))
注意事项
- 若数据来源不可信,建议避免使用
eval(),优先选择正则表达式解析; - 映射字典可根据实际需求扩展更多扑克牌面的转换规则;
- 所有方法均实现了逐行判断处理,解决了原代码整列赋值的问题。
内容的提问来源于stack exchange,提问作者Raphaël Ambit
相关产品推荐
相关产品推荐

