Pandas Dataframe:对于给定的行,尝试基于在另一列中查找值来分配特定列中的值

时间:2018-11-21 20:31:54

标签: python pandas

基本上,对于给定的行i,我试图根据另一列“本地最大字符串”中i的值,将“ Adj”列中的i值分配给某个值。基本上,需要在DataFrame的另一列“日期字符串”中搜索“本地最大字符串”中的第i行的值,然后,包含值q的行在“调整结束”列中具有该值。第i行的“ Adj”列的值。

抱歉,这很难理解。下面的for循环完成了我想做的事情,但是我认为在Pandas中应该有更好的方法。我尝试使用apply和lambda函数,但是它说不可能进行赋值,而且我不确定我的操作方式是否正确。 for循环还需要很长时间才能完成。

代码如下:

for x in range(0, len(df.index)):
    df['Adj'][x] = df.loc[df['Date String'] == df['Local Max String'][x]]['Adj Close']

下面是DF的图片,可以更好地理解我的意思。 “调整”列中的值将查找与“本地最大字符串”中的“日期”相对应的“调整结束”值。

enter image description here

import numpy as np
import pandas as pd
pd.core.common.is_list_like = pd.api.types.is_list_like
from pandas_datareader import data as pdr
import matplotlib.pyplot as plt
import datetime
import fix_yahoo_finance as yf
yf.pdr_override() # <== that's all it takes :-)

# Dates for data
start_date = datetime.datetime(2017,11,1)
end_date = datetime.datetime(2018,11,1)

df = pdr.get_data_yahoo('SPY', start=start_date, end=end_date)

df.data = df['Adj Close']
df['Most Recent Local Max'] = np.nan
df['Date'] = df.index
local_maxes = list(df[(df.data.shift(1) < df.data) & (df.data.shift(-1) < df.data)].index)
local_maxes.append(df['Date'][0] - datetime.timedelta(days=1))

def nearest(items, pivot):
    return min([d for d in items if d< pivot], key=lambda x: abs(x - pivot))

df['Most Recent Local Max'] = df['Date'].apply(lambda x: min([d for d in local_maxes if d < x], key=lambda y: abs(y - x)) )

df['Local Max String'] = df['Most Recent Local Max'].apply(lambda x: str(x))

df['Date String'] = df['Date'].apply(lambda x: str(x))

df.loc[df['Local Max String'] == str(df['Date'][0] - datetime.timedelta(days=1)), 'Local Max String'] = str(df['Date'][0])

df['Adj'] = np.nan

谢谢!

2 个答案:

答案 0 :(得分:0)

此解决方案仍然具有for,但是它将迭代次数从df.shape[1]减少到df['Local Max String'].nunique(),因此它可能足够快:

for a_local_max in df['Local Max String'].unique():
    df.loc[df['Date String'] == a_local_max, 'Adj'] = df.loc[df['Local Max String'] == a_local_max, 'Adj Close'].iloc[0]

答案 1 :(得分:0)

通常,您可以在pandas中使用类似于apply的函数来跳过for循环。此后,我定义了一个wrapper函数,该函数按行组合变量。 最后,将此函数应用于数据框以创建result变量。此处的关键元素是思考wrapper函数中的行级别,并使用apply参数向axis=1函数指示此行为。

import pandas as pd
import numpy as np

# Dummy data containing two columns with overlapping data
df = pd.DataFrame({'date': 100*np.random.sample(10000), 'string': 2500*['hello', 'world', '!', 'mars'], 'another_string': 10000*['hello']})

# Here you define the operation at the row level
def wrapper(row):
#     uncomment if the transformation is to be applied to every column:
#     return 2*row['date']
#     if you need to first test some condition:
    if row['string'] == row['another_string']:
        return 2*row['date']
    else:
        return 0

# Finally you generate the new column using the operation defined above.
df['result'] = df.apply(wrapper, axis=1)

此代码在每循环195 ms±1.96 ms内完成(平均±标准偏差,共运行7次,每个循环1次)