在R中用kNN插补缺失值报错,寻求周末股价NA插补可行方案
Hey there! Let's break down your problem step by step—no fancy jargon, just straightforward explanations since you're still learning this stuff!
First, let's tackle that error you got with kNN. Looking at your code:
kNN(Oriental_Stock, variable = colnames("Stock"), k = 2)
The immediate issue is colnames("Stock")—since "Stock" is just a string, colnames() returns NULL, which messes up the variable parameter. Even if you fixed that to variable = "Stock", kNN still isn't the best fit for your specific need. Here's why:
kNN fills missing values by finding the numerically closest data points, not the time-ordered adjacent ones. For your stock data, you specifically want to use Friday and Monday values (the exact days around the weekend) to calculate the average—but kNN might pick completely different days if their stock prices are closer numerically, which isn't what you want.
A Simpler, Targeted Solution
Since your missing values follow a strict pattern (weekends = NA), we can use time-series-specific filling that directly uses the Friday/Monday values you care about. Here are two easy methods:
1. Using Base R (No Extra Packages Needed)
If you don't want to install new packages, you can manually grab the nearest non-missing values:
# Create a copy of your stock column to fill Oriental_Stock$Stock_imputed <- Oriental_Stock$Stock # Find all positions with NA values na_positions <- which(is.na(Oriental_Stock$Stock)) # Loop through each NA to calculate the Friday-Monday average for (pos in na_positions) { # Get the last non-NA value (Friday) friday_val <- Oriental_Stock$Stock[max(which(!is.na(Oriental_Stock$Stock[1:pos])))] # Get the next non-NA value (Monday) monday_val <- Oriental_Stock$Stock[min(which(!is.na(Oriental_Stock$Stock[pos:length(Oriental_Stock$Stock)])) + pos - 1)] # Fill the NA with the average Oriental_Stock$Stock_imputed[pos] <- (friday_val + monday_val)/2 }
2. Using the zoo Package (Cleaner & Faster)
The zoo package has built-in functions to handle forward/backward filling, which makes this task way simpler:
# Install the package (only need to do this once) install.packages("zoo") library(zoo) # Forward fill: replace NA with the last non-NA value (Friday for weekends) forward_fill <- na.locf(Oriental_Stock$Stock) # Backward fill: replace NA with the next non-NA value (Monday for weekends) backward_fill <- na.locf(Oriental_Stock$Stock, fromLast = TRUE) # Calculate the average for all NA positions Oriental_Stock$Stock_imputed <- ifelse(is.na(Oriental_Stock$Stock), (forward_fill + backward_fill)/2, Oriental_Stock$Stock)
Testing With Your Sample Data
Using your example data:
Oriental_Stock <- data.frame(Stock = c(42.80, 43.05, 43.00, 43.00, 42.20, NA, NA, 42.50, 40.00, 40.25, 40.55, 41.50, NA, NA, 40.85))
After running the zoo code, the first two NAs (weekend) will be filled with (42.20 + 42.50)/2 = 42.35, and the next two NAs will get (41.50 + 40.85)/2 = 41.175—exactly what you wanted!
Quick Note on kNN (If You Want to Experiment)
If you still want to try kNN for learning, fix the variable parameter first:
kNN(Oriental_Stock, variable = "Stock", k = 2)
But keep in mind this won't give you the Friday-Monday average you need—it'll pick the two numerically closest stock prices, which might not align with the weekend timeline.
Hope this helps! Feel free to ask if you need clarification on any part of the code.
内容的提问来源于stack exchange,提问作者Valeriya

