我正在尝试根据当前数据集为模型创建训练数据集。它用于二十一点,每一行都是玩家玩牌的方式。
表格可能看起来像这样:
|Card1|Card2|Card3|Card4|Card5|PlayerTotal|DealerCard1|Win/Lose
| 7 | 10 | 0 | 0 | 0 | 17 | 10 | 0
| 4 | 3 | 10 | 0 | 0 | 17 | 8 | 1
我想把它变成只有玩家手牌、庄家牌和赢/输的总和的行。但是,如果打出超过 2 张牌(因此玩家击中),那么我想在每个阶段为游戏样本制作多行(所以在玩家每次击中之前)
所以这个例子会变成:
|PlayerTotal|DealerCard1|Win/Lose
| 17 | 10 | 0
| 7 | 8 | 1
| 17 | 8 | 1
我怎样才能有效地做到这一点?
我可以使用 pd.apply 和带有 if 语句的自定义函数来处理小型数据集,但一旦我使用了整个数据集(~1 mill 点),它就会变得非常慢且占用大量内存。
像这样:
def extractRounds(x):
totals = []
totals.append(x[0:2], x[5], x[6]])
if x[2] > 0:
totals.append([sum(x[0:3]), x[5], x[6]])
else:
return pd.Series(totals)
if x[3] > 0:
totals.append([sum(x[0:4]), x[5], x[6]])
else:
return pd.Series(totals)
if x[4] > 0:
totals.append([sum(x[0:5]), x[5], x[6]])
return pd.Series(totals)
b = (a.apply(extractRounds, axis = 1)).stack()
我猜 extractRounds(x)
函数不是最有效的。
所以我想知道我尝试通过对每一行应用一个函数来做到这一点是否找错了树,或者是否有更好的方法?
如果不清楚,请告诉我。干杯!
最佳答案
您可以使用 melt 将数据转换为长格式,添加累计和,然后只排除卡片 3-5 的零卡片值。并排除卡 1,因为玩家总是至少有 2 张卡。
这是您作为数据框的示例:
import pandas as pd
import numpy as np
raw = pd.DataFrame({'Card1': [7, 4],
'Card2': [10, 3],
'Card3': [0, 10],
'Card4': [0, 0],
'Card5': [0, 0],
'DealerCard1': [10, 8],
'PlayerTotal': [17, 17],
'Win/Lose': [0, 1]})
raw.index.name = 'Game'
使用 melt 创建另一个长格式的数据框:
df = (raw.reset_index()
.melt(value_vars=['Card1', 'Card2', 'Card3', 'Card4', 'Card5'],
id_vars=['Game', 'DealerCard1', 'Win/Lose'],
value_name='CardValue',
var_name='Card')
.sort_values('Game')
.reset_index(drop=True))
将 PlayerTotal 列重新创建为累计总和:
df['PlayerTotal'] = df.groupby('Game')['CardValue'].apply(np.cumsum)
然后您可以只排除卡片 1 和零卡片并选择您想要的列:
df.loc[(df['CardValue']!=0) & (df['Card']!='Card1'), ['PlayerTotal', 'DealerCard1', 'Win/Lose']]
这会给你:
PlayerTotal DealerCard1 Win/Lose
1 17 10 0
6 7 8 1
7 17 8 1
关于python - 如何有效地将函数应用于 Pandas 数据框的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56553026/