簡體   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