繁体   English   中英

如何有效地将函数应用于大型pandas数据帧的行?

[英]How to efficiently apply function to rows of large pandas data frame?

我试图从当前数据集为模型创建训练数据集。 它用于二十一点,每一行都是玩家如何玩牌。

该表可能如下所示:

|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张牌(因此播放器命中),那么id喜欢在每个阶段使用游戏为该样本制作多行(所以在播放器每次击中之前)

所以这个例子将成为:

|PlayerTotal|DealerCard1|Win/Lose
|    17     |     10    |  0
|    7      |     8     |  1
|    17     |     8     |  1

我怎样才能有效地做到这一点?

我可以使用pd.apply的小数据集和if语句的自定义函数来做这件事,但是一旦我使用整个数据集(~1毫分),它的速度非常慢且占用大量内存。

像这样的东西:

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)函数不是最有效或最有效的。

所以,我想知道我是否正在试图通过对每一行应用一个函数或者如果有更好的方法来实现这个错误的树?

如果不清楚,请告诉我。 干杯!

您可以使用“融合”将数据转换为长格式,添加累积总和,然后只排除卡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

您可以使用命令行工具将额外的行添加到csv文件并进行求和。

我们先说几行CSV文件data.csv

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

运行以下命令可以获得所需的输出

sed 's/\(.*,\)\(.*,\)\([1-9][0-9]*,\)\(.*,.*,.*,.*,.*\)/\1\2\3\4\n\1\20,\4/' data.csv | cut -d ',' -f 1,2,3,7,8 | awk -F ',' 'NR>1 {print $1+$2+$3 "," $4 "," $5}' > data_2.csv

它创建一个名为data_2.csv的文件

17,10,0
17,8,1
7,8,1

--------------------------------

命令说明:

sed 's/\(.*,\)\(.*,\)\([1-9][0-9]*,\)\(.*,.*,.*,.*,.*\)/\1\2\3\4\n\1\20,\4/' data.csv

data.csv读取data.csv ,如果第三列中的行具有0值,则在第三data.csv 0时添加另一行。

| cut -d ',' -f 1,2,3,7,8

从上一步读取数据并将数据过滤到第1,2,3,7,8列(这些是我们关心的列)

| awk -F ',' 'NR>1 {print $1+$2+$3 "," $4 "," $5}' > data_2.csv

从上一步读取数据,将前三列相加,并将其与最后两列一起写入名为data_2.csv的文件中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM