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

标签 python pandas numpy dataframe

注意,如果复制,我的代码就会运行

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

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

然后我获取所需的数据并创建名为 df 的新 df

然后必须在 df 中的每一行上运行函数 trade,简单的看跌期权如果价格高于滚动平均值,则买入;如果低于滚动平均值,则卖出,此数据为然后保存在log中。

我在 df 中的每一行应用此函数时遇到问题。

我使用行 log = df.apply(lambda x: trade(x['date'], x['close'], x['MA']), axis=1) 取得了巨大成功 但令人惊讶的是,当 API 调用中使用 BTC_ETH 而不是其他(即 BTC_FCT 或 BTC_DOGE)时,尽管数据形式相同,它仍然有效。使用 ETH 创建 DataFrame(这就是我想要的) DOGE 和 FCT 创建一个系列

第一个问题,如何在每一行上运行我的 trade 函数并使用结果创建一个新的 df log

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

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)

编辑:

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

def trade(date, close, MA):#, port):
    #d = {'Data': close}
    #test_log = test_log.append(d, ignore_index=True)

    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']}
        data_list.append(d)

        #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']}

        data_list.append(d)

        #return pd.Series(d) 


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

log = log.dropna()

for key,value in port.items():
    print(key, value )

log.from_dict(data_list)

最佳答案

问题是您并不总是在 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 ,事实上我认为在您的情况下它可能不会产生正确的结果。

关于python - 如何在 DataFrame 中的每一行上运行函数并将结果附加到新的 DataFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41984807/

相关文章:

python - 如何处理 Keras 中超长的卷积序列内存大小?

python - 用 pandas 平均二维地理数据

python - 提取 DataFrame 的扩展窗口(numpy strided)

python - 在 numpy 一维数组中查找拐点和固定点

Python:单独取矩阵每一行的外积,取和然后返回一个和向量

python - multiprocess.apply_async 如何包装 *args 和 **kwargs?

python - 循环 Python 解码器环中字符串中的每个字符

python - 获取 pandas 数据框中一列中 n 个单词的前 n/2 个

python - 循环遍历python中的数据帧字典

python - 2d numpy 数组,使每个值成为它以其为中心的 3x3 正方形的总和