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

Python 如何在DataFrame中的每一行上运行函数并将结果附加到新DataFrame,python,pandas,numpy,dataframe,Python,Pandas,Numpy,Dataframe,注意:如果复制,我的代码将运行 我编写了一个简单的脚本,使用poloniex API对加密货币进行回溯测试 首先,我从API请求数据,并将其转换为数据帧data 然后,我获取所需的数据,并创建名为df 然后,必须在df中的每一行上运行一个函数trade,如果价格高于其购买和销售的滚动平均值,则简单地将该数据保存在log中 在df中的每一行应用此函数时遇到问题 我在使用行log=df.apply(lambda x:trade(x['date'],x['close'],x['MA']),axis=1

注意:如果复制,我的代码将运行

我编写了一个简单的脚本,使用poloniex API对加密货币进行回溯测试

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

然后,我获取所需的数据,并创建名为
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会创建数据帧(这是我想要的),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)
将numpy导入为np
从熊猫导入系列,数据帧
作为pd进口熊猫
空气污染指数https://poloniex.com/public?command=returnChartData¤cyPair=BTC_FCT&start=1435699200&end=9999999999&period=86400'
data=pd.read\u json(API)
df=pd.DataFrame(列={'date','close','MA'})
df.MA=pd.滚动平均值(data.close,30)
df.close=data.close
df.date=data.date
df=df.truncate(在=29之前)
def打印满(x):
pd.set_选项('display.max_rows',len(x))
打印(x)
pd.reset\u选项('display.max\u rows')
log=pd.DataFrame(列=['Date','type','profit','port_value'])
端口={'coin':0,'BTC':1}
def交易(日期、截止日期、MA):
如果MA<关闭且端口['coin']==0:
购买的硬币=港口['BTC']/MA
端口['BTC']=0
端口['coin']=您购买的硬币
d={'Date':日期,'type':'buy','coin_value':端口['coin'],'btc_value':端口['btc']}
返回pd系列(d)
elif MA>关闭和端口['BTC']==0:
已售出的硬币=港口['coin']*MA
端口['coin']=0
端口['BTC']=已售出的硬币
d={'Date':日期,'type':'sell','coin_value':端口['coin'],'btc_value':端口['btc']}
打印()
返回pd系列(d)
log=df.apply(λx:trade(x['date'],x['close'],x['MA']),axis=1)
log=log.dropna()
打印完整(日志)
编辑:

我解决了这个问题,通过将dict追加到list中,然后使用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)
def交易(日期、截止日期、马萨诸塞州):#,港口):
#d={'Data':关闭}
#test\u log=test\u log.append(d,ignore\u index=True)
如果MA<关闭且端口['coin']==0:
购买的硬币=港口['BTC']/MA
端口['BTC']=0
端口['coin']=您购买的硬币
d={'Date':日期,'type':'buy','coin_value':端口['coin'],'btc_value':端口['btc']}
数据列表。附加(d)
#返回pd系列(d)
elif MA>关闭和端口['BTC']==0:
已售出的硬币=港口['coin']*MA
端口['coin']=0
端口['BTC']=已售出的硬币
d={'Date':日期,'type':'sell','coin_value':端口['coin'],'btc_value':端口['btc']}
数据列表。附加(d)
#返回pd系列(d)
df.apply(λx:trade(x['date'],x['close'],x['MA']),axis=1)
log=log.dropna()
对于键,port.items()中的值:
打印(键、值)
日志从目录(数据列表)

问题在于,您并非总是在
交易中返回一个值,这令人困惑。试试这个:

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)
将numpy导入为np
从熊猫导入系列,数据帧
作为pd进口熊猫
空气污染指数https://poloniex.com/public?command=returnChartData¤cyPair=BTC_FCT&start=1435699200&end=9999999999&period=86400'
data=pd.read\u json(API)
df=pd.DataFrame(列={'date','close','MA'})
df.MA=pd.滚动平均值(data.close,30)
df.close=data.close
df.date=data.date
df=df.truncate(在=29之前)
def打印满(x):
pd.set_选项('display.max_rows',len(x))
打印(x)
pd.reset\u选项('display.max\u rows')
log=pd.DataFrame(列=['Date','type','profit','port_value'])
端口={'coin':0,'BTC':1}
端口={'coin':0,'BTC':1}
def交易(日期、截止日期、MA):
d={'Date':Date,'type':'','coin_value':np.nan,'btc_value':np.nan}
如果MA<关闭且端口['coin']==0:
购买的硬币=港口['BTC']/MA
端口['BTC']=0
端口['coin']=您购买的硬币
d['type']='buy'
d['coin_value']=端口['coin']
d['btc_值']=端口['btc']
elif MA>关闭和端口['BTC']==0:
已售出的硬币=港口['coin']*MA
端口['coin']=0
端口['BTC']=已售出的硬币
d['type']='sell'
d['coin_value']=端口['coin']
d['btc_值']=端口['btc']
返回pd系列(d)
log=df.apply(λx:trade(x['date'],x['close'],x['MA']),axis=1)
log=log.dropna()
打印完整(日志)

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

根据,使用具有副作用的函数(如您的函数)可能会导致意外行为,因为它在第一行被调用两次(请参阅“注意事项”).非常感谢您的时间,我实际上刚刚解决了这个问题,请参阅2分钟后的帖子了解更多信息edits@DavidHancock事实上,如果你已经解决了这个问题,也许最好不要编辑你原来的帖子,然后发布你的修复作为答案?(如果是别的)