如何在DataFrame中的每一行上运行函数,并将结果附加到新的DataFrame

时间:2017-02-01 16:30:06

标签: python pandas numpy dataframe

注意我的代码在复制后运行

我写了一个简单的脚本来使用poloniex API来回测加密货币。

首先,我从API请求数据并将其转换为数据框data

然后我获取我想要的数据并创建名为df

的新df

然后必须在trade中的每一行上运行一个函数df,如果价格高于其买入和卖出的滚动平均值,则简单放置,如果低于此值,则此数据将保存在{{1}中}}

我在log的每一行上应用此功能时遇到问题。

我使用行df取得了巨大的成功但令人惊讶的是,当在API调用中使用BTC_ETH而不是其他人时,即BTC_FCT或BTC_DOGE,尽管数据形式相同,但它仍然有效。使用ETH导致创建DataFrame(这就是我想要的)DOGE和FCT创建一个系列

第一个问题,我如何在每一行上运行log = df.apply(lambda x: trade(x['date'], x['close'], x['MA']), axis=1)函数,并使用结果创建一个新的trade

奖金问题,即使数据类型相同,为什么它适用于ETH而不适用于DOGE / FCT?

log

编辑:

我解决了这个问题,我通过将dicts附加到list然后使用df.from_dict()方法来创建日志数据帧来修复它,我的代码只是为了澄清。

import numpy as np
from pandas import Series, DataFrame
import pandas as pd

API = 'https://poloniex.com/public?command=returnChartData&currencyPair=BTC_FCT&start=1435699200&end=9999999999&period=86400'
data = pd.read_json(API)

df = pd.DataFrame(columns = {'date','close','MA'})

df.MA = pd.rolling_mean(data.close, 30)
df.close = data.close
df.date = data.date

df = df.truncate(before=29)

def print_full(x):
    pd.set_option('display.max_rows', len(x))
    print(x)
    pd.reset_option('display.max_rows')

log = pd.DataFrame(columns = ['Date', 'type', 'profit', 'port_value'])
port = {'coin': 0, 'BTC':1}

def trade(date, close, MA):

    if MA < close and port['coin'] == 0 :

        coins_bought = port['BTC']/MA

        port['BTC'] = 0
        port['coin'] = coins_bought

        d = {'Date':date, 'type':'buy', 'coin_value': port['coin'], 'btc_value':port['BTC']}
        return pd.Series(d) 

    elif MA > close and port['BTC'] == 0 :

        coins_sold = port['coin']*MA

        port['coin'] = 0
        port['BTC'] = coins_sold

        d = {'Date':date, 'type':'sell', 'coin_value': port['coin'], 'btc_value':port['BTC']}
        print()
        return pd.Series(d) 

log = df.apply(lambda x: trade(x['date'], x['close'], x['MA']), axis=1)

log = log.dropna()

print_full(log)

1 个答案:

答案 0 :(得分:1)

问题在于你并不总是在trade中返回一个值,这让Pandas感到困惑。试试这个:

import numpy as np
from pandas import Series, DataFrame
import pandas as pd

API = 'https://poloniex.com/public?command=returnChartData&currencyPair=BTC_FCT&start=1435699200&end=9999999999&period=86400'
data = pd.read_json(API)

df = pd.DataFrame(columns = {'date','close','MA'})

df.MA = pd.rolling_mean(data.close, 30)
df.close = data.close
df.date = data.date

df = df.truncate(before=29)

def print_full(x):
    pd.set_option('display.max_rows', len(x))
    print(x)
    pd.reset_option('display.max_rows')

log = pd.DataFrame(columns = ['Date', 'type', 'profit', 'port_value'])
port = {'coin': 0, 'BTC':1}

port = {'coin': 0, 'BTC':1}

def trade(date, close, MA):
    d = {'Date': date, 'type':'', 'coin_value': np.nan, 'btc_value': np.nan}

    if MA < close and port['coin'] == 0 :
        coins_bought = port['BTC']/MA
        port['BTC'] = 0
        port['coin'] = coins_bought
        d['type'] = 'buy'
        d['coin_value'] = port['coin']
        d['btc_value'] = port['BTC']

    elif MA > close and port['BTC'] == 0 :
        coins_sold = port['coin']*MA
        port['coin'] = 0
        port['BTC'] = coins_sold
        d['type'] = 'sell'
        d['coin_value'] = port['coin']
        d['btc_value'] = port['BTC']

    return pd.Series(d)

log = df.apply(lambda x: trade(x['date'], x['close'], x['MA']), axis=1)

log = log.dropna()

print_full(log)

但是,正如我在评论中提到的,将带有副作用的函数传递给apply并不是一个好主意according to the documentation,事实上我认为它可能无法在您的评论中产生正确的结果情况下。