使用purrr执行逐行操作时遇原子向量$访问错误求助
Hey there! Let's break down why you're getting that "cannot use $ operator on atomic vector" error and fix it with purrr (or a few other straightforward approaches).
The Root of the Problem
When you use apply(iris, 1, test_function), apply converts each row of your data frame into an atomic vector (not a single-row data frame object). Your function relies on the $ operator, which only works with lists or data frames—atomic vectors don't recognize this syntax, hence the error.
Fix 1: Use purrr to Pass Rows as Data Frames
Since you wanted to use purrr anyway, this is the cleanest, most idiomatic approach. We’ll split the iris data frame into a list of single-row data frames, then use map_df to apply your function and automatically bind the results into a single data frame:
library(purrr) library(dplyr) test_function = function(dat_) { petal_width = dat_$Petal.Width sepal_width = dat_$Sepal.Width petal_length = dat_$Petal.Length sepal_length = dat_$Sepal.Length tibble(petal_length, sepal_length, sepal_width, petal_width) } # Split iris into list of single-row data frames, then apply function result <- iris %>% split(seq(nrow(.))) %>% map_df(test_function)
Fix 2: Adjust Your Function to Work with Atomic Vectors
If you still want to use apply, modify your function to use [[]] instead of $—this operator works with both data frames and named atomic vectors (which apply produces here):
test_function = function(dat_) { # Use [[]] to handle both data frames and atomic vectors petal_width = dat_[["Petal.Width"]] sepal_width = dat_[["Sepal.Width"]] petal_length = dat_[["Petal.Length"]] sepal_length = dat_[["Sepal.Length"]] tibble(petal_length, sepal_length, sepal_width, petal_width) } # Now apply runs without errors result <- apply(iris, 1, test_function) %>% bind_cols()
Fix 3: Convert Vectors to Data Frames in apply
A quick workaround is to convert each atomic vector back to a data frame before passing it to your function:
result <- apply(iris, 1, function(row) test_function(as.data.frame(t(row)))) %>% bind_cols()
A Quick Simplification
You can also streamline your function to avoid repetitive column extractions—since all you’re doing is rearranging columns, this shorter version works just as well:
test_function = function(dat_) { dat_ %>% select(Petal.Length, Sepal.Length, Sepal.Width, Petal.Width) }
This works seamlessly with both single-row data frames (from purrr) and converted vectors (from the other fixes).
内容的提问来源于stack exchange,提问作者spazznolo

