我有一个简单的股票价格表,我们称之为“价格”,#34;沿着顶部的代码和沿着边的日期。
我想创建一个新表," price_norm,"它将每个价格除以第一个价格。例如,第一列可能如下所示:
price price_norm
20.00 1.000
21.00 1.050
21.00 1.050
20.00 1.000
20.50 1.025
...等
皱纹是有些股票一直没有定价回到第一个日期,所以他们的专栏在"价格"从一串NA开始 - 在这种情况下,它们应该除以第一个非NA值,而不是第一行中的值。
可能还有一些股票没有任何价格,其中每个价值都是NA;在这种情况下,price_norm中的相应列也应该都是NA。
我以一种非常缓慢的方式完成了这项工作 - 30秒或更长时间来处理。我正在寻找一种更有效的方式:
price_norm <- price
nonNAIndex <- function(z) {
min(which(!is.na(z)))
}
for( j in colnames(price) ) {
if(!is.na(price[nrow(price),j])) {
k <- nonNAIndex(price[,j])
for( i in k:nrow(price) ) {
price_norm[i,j] <- ( price[i,j] / price[k,j] )
}
}
}
答案 0 :(得分:2)
以下听起来应该做你想做的事:
## sample data
mydf <- data.frame(v1 = c(20.00, 21.00, 21.00, 20.00, 20.50),
v2 = c(NA, 20.00, 21.00, 21.00, 20.00),
v3 = NA)
mydf / lapply(mydf, function(x) ifelse(all(is.na(x)), NA, na.omit(x)[1]))
# v1 v2 v3
# 1 1.000 NA NA
# 2 1.050 1.00 NA
# 3 1.050 1.05 NA
# 4 1.000 1.05 NA
# 5 1.025 1.00 NA
我刚刚创建了一个初始值列表,并将原始data.frame
除以这些值。
答案 1 :(得分:0)
确保您的数据为data.frame
sapply(df, function(x) {x/ifelse(all(is.na(x)), NA, head(x[!is.na(x)],1))})
答案 2 :(得分:0)
或者您可以尝试:(使用@Ananda Mahto的数据集)
m1 <- t(mydf)
mydf/as.list(m1[cbind(1:nrow(m1),max.col(!is.na(m1), "first"))])
稍微大一点的数据集
set.seed(24)
df <- as.data.frame(matrix(sample(c(NA,1:25), 1e3*2e3, replace=TRUE), ncol=2e3))
f1 <- function() df/lapply(df, function(x) ifelse(all(is.na(x)), NA, na.omit(x)[1]))
f2 <- function() sapply(df, function(x) {x/ifelse(all(is.na(x)), NA, head(x[!is.na(x)],1))})
f3 <- function() {m1 <- t(df)
df/as.list(m1[cbind(1:nrow(m1),max.col(!is.na(m1), "first"))])}
library(microbenchmark)
microbenchmark(f1(), f2(), f3(), unit="relative", times=25L)
#Unit: relative
#expr min lq median uq max neval
#f1() 1.213922 1.197350 1.140682 1.103249 1.351307 25
#f2() 6.318962 6.925681 7.212136 6.370824 8.080331 25
#f3() 1.000000 1.000000 1.000000 1.000000 1.000000 25