【问题标题】:Replacing only NA values in xts object column wise using specific formula使用特定公式仅替换 xts 对象列中的 NA 值
【发布时间】:2020-03-30 10:52:59
【问题描述】:

我想用公式 Beta * Exposure * Index return 替换我的 xts 对象中的 NA 值。 我的 xts 对象是假设下面创建的 Position_SimPnl:

library(xts)    
df1 <- data.frame(Google = c(NA, NA, NA, NA, 500, 600, 700, 800),
                    Apple = c(10, 20,30,40,50,60,70,80),
                    Audi = c(1,2,3,4,5,6,7,8),
                    BMW = c(NA, NA, NA, NA, NA, 6000,7000,8000),
                    AENA = c(50,51,52,53,54,55,56,57))

Position_SimPnl <- xts(df1, order.by = Sys.Date() - 1:8)

对于 Beta,有一个特定的数据框:

Beta_table <- data.frame (AENA = c(0.3,0.5,0.6), Apple = c(0.2,0.5,0.8), Google = c(0.1,0.3,0.5), Audi = c(0.4,0.6,0.7), AXP = c(0.5,0.7, 0.9), BMW = c(0.3,0.4, 0.5))
rownames(Beta_table) <- c(".SPX", ".FTSE", ".STOXX")

为了曝光,还有另一个数据框:

Base <- data.frame (RIC = c("AENA","BMW","Apple","Audi","Google"), Exposure = c(100,200,300,400,500))

对于索引返回,有一个 xts 对象(Index_FX_Returns):

    df2 <- data.frame(.SPX = c(0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08),
                    .FTSE = c(0.5, 0.4,0.3,0.2,0.3,0.4,0.3,0.4),
                    .STOXX = c(0.15,0.25,0.35,0.3,0.45,0.55,0.65,0.5))

Index_FX_Returns <- xts(df2,order.by = Sys.Date() - 1:8)

还有一个将 RIC 与索引链接的数据框:

RIC_Curr_Ind <- data.frame(RIC = c("AENA", "Apple", "Google", "Audi", "BMW"), Currency = c("EUR.","USD.","USD.","EUR.","EUR."), Index = c(".STOXX",".SPX",".SPX",".FTSE",".FTSE"))

我想要的是对于 Position_SimPnl 中 NA 值的特定位置,它应该查看列名并从 RIC_Curr_Ind 数据帧中获取相应的索引名称,然后通过匹配列名(NA 的列名)从 Beta_table 中查找 beta 值) 和行名(从 NA 的列名派生的索引名)。 然后再次通过将 Position_SimPnl 中的列名与“Base”数据帧中的 RIC 列进行匹配,它将提取相应的曝光值。 然后通过将 Position_SimPnl 中的列名与 RIC_Curr_Ind 数据帧中的 RIC 列进行匹配,它将获得相应的索引名称,并从该索引名称中查找 xts 对象 Index_FX_Returns 的列名称,并获得与NA值。

在获得 Beta、Exposure 和 Index 返回值后,我希望将 NA 值替换为公式:Beta * Exposure * Index return。此外,我只想替换 Position_SimPnl 中的 NA 值。其他值应保持原样。我使用以下公式替换 NA 值:

do.call(merge, lapply(Position_SimPnl, function(y) {if(is.na(y)){y = (Beta_table[match(RIC_Curr_Ind$Index[match(colnames(y),RIC_Curr_Ind$RIC)],rownames(Beta_table)), match(colnames(y),colnames(Beta_table))]) * (Base$Exposure[match(colnames(y), Base$RIC)]) * (Index_FX_Returns[,RIC_Curr_Ind$Index[match(colnames(y),RIC_Curr_Ind$RIC)]])} else{y}}))

但是,在输出中,如果特定列包含 NA,它将替换列中的所有值(包括以前不是 NA 的值)。我也收到多条警告消息,例如 “在 if (is.na(y)) { ... : 条件的长度 > 1,并且只使用第一个元素”。 我认为正因为如此,所有列的值都在转换,包括非 NA 值。任何人都可以建议如何通过上述公式有效地替换这些 NA 值,同时保持其他值相同。任何帮助将不胜感激

【问题讨论】:

  • 谢谢...我已采纳您的建议并相应地编辑了我的问题。
  • 您需要决定哪一天 Beta * Exposure * Index 因为将有三个值来替换位置 NA(因为每个 RIC 有 3 个索引)。三者的平均值/中位数?最小/最大三个?
  • 如果您看到 RIC_Curr_Ind 数据帧,则每个 RIC 仅映射到“.STOXX”、“.SPX”或“.FTSE”中的一个索引。所以 BetaExposureIndex 只有一个唯一值。
  • @Parfait :非常感谢您的回复。这是有效的。我还想问是否可以通过调整我在使用 lapply 函数的帖子中提到的代码来获得相同的输出。我的代码正在运行,但它正在将包含非 NA 的列(包含 NA 的列)的所有值转换为 Beta * Exposure * Index return

标签: r lapply na xts


【解决方案1】:

因为您需要组合所有数据集以实现您的公式Beta * Exposure * Index,因此请考虑构建一个包含所有所需组件的主数据框。但是,您面临两个挑战:

  • 不同的数据类型(xts 对象和数据框)
  • 不同的数据格式(widelong 格式)

为了正确合并和计算,请考虑将所有数据组件转换为数据帧并重新整形为长格式(即除BaseRIC_Curr_Ind 之外的所有数据)。然后,merge 并用ifelse 计算以填充NA 值。当然,最后,您将不得不重新调整为宽并转换回 XTS。

重塑

# USER-DEFINED METHOD GIVEN THE MULTIPLE CALLS 
proc_transpose <- function(df, col_pick, val_col, time_col) {
  reshape(df, 
          varying = names(df)[col_pick],
          times = names(df)[col_pick], ids = NULL,
          v.names = val_col, timevar = time_col,
          new.row.names = 1:1E4, direction = "long")
}

# POSITIONS
Position_SimPnl_wide_df <- data.frame(date = index(Position_SimPnl), 
                                      coredata(Position_SimPnl))

Position_SimPnl_long_df <- proc_transpose(Position_SimPnl_wide_df, col_pick = -1,
                                          val_col = "Position", time_col = "RIC")

# BETA
Beta_table_long_df <- proc_transpose(transform(Beta_table, Index = row.names(Beta_table)),
                                     col_pick = 1:ncol(Beta_table),
                                     val_col = "Beta", time_col = "RIC")

# INDEX
Index_FX_Returns_wide_df <- data.frame(date = index(Index_FX_Returns),
                                  coredata(Index_FX_Returns))

Index_FX_Returns_long_df <- proc_transpose(Index_FX_Returns_wide_df, col = -1,
                                           val_col = "Index_value", time_col = "Index")

合并

# CHAIN MERGE
master_df <- Reduce(function(...) merge(..., by="RIC"), 
                    list(Position_SimPnl_long_df, 
                         Beta_table_long_df, 
                         Base)
                    )

# ADDITIONAL MERGES (NOT INCLUDED IN ABOVE CHAIN DUE TO DIFFERENT by)
master_df <- merge(master_df,
                   Index_FX_Returns_long_df, by=c("Index", "date"))

master_df <- merge(master_df,
                   RIC_Curr_Ind, by=c("Index", "RIC"))

计算

# FORMULA: Beta * Exposure * Index 
master_df$Position <- with(master_df, ifelse(is.na(Position),  
                                             Beta * Exposure * Index_value, 
                                             Position))

最后的准备

# RE-ORDER ROWS AND SUBSET COLS
master_df <- data.frame(with(master_df, master_df[order(RIC, date), 
                                                  c("date", "RIC", "Position")]),
                        row.names = NULL)

# RESHAPE WIDE (REVERSE OF ABOVE)
Position_SimPnl_new <- setNames(reshape(master_df, idvar = "date",
                                        v.names = "Position", timevar = "RIC",
                                        direction = "wide"),
                                c("date", unique(master_df$RIC)))

# CONVERT TO XTS
Position_SimPnl_new <- xts(transform(Position_SimPnl_new, date = NULL),
                           order.by = Position_SimPnl_new$date)

Position_SimPnl_new 

#            AENA Apple Audi  BMW Google
# 2019-11-27   58    80    8 8000  800.0
# 2019-11-28   57    70    7 7000  700.0
# 2019-11-29   56    60    6 6000  600.0
# 2019-11-30   55    50    5   24  500.0
# 2019-12-01   54    40    4   16    2.0
# 2019-12-02   53    30    3   24    1.5
# 2019-12-03   52    20    2   32    1.0
# 2019-12-04   51    10    1   40    0.5

【讨论】:

  • :非常感谢您的回复。这是有效的。我还想问是否可以通过调整我在使用 lapply 函数的帖子中提到的代码来获得相同的输出。我的代码正在运行,但它正在将包含非 NA 的列(包含 NA 的列)的所有值转换为 BetaExposureIndex 返回。
  • 原谅我,但我不推荐您尝试的可读性、可维护性和效率的方法(因为这里没有使用循环,例如lapply,而是矢量化ifelse)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-19
  • 1970-01-01
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多