R语言用for循环批量处理数据框列表时遇行数不匹配错误求助
R语言批量处理拆分后的数据框列表报错排查与解决
我最近在处理R语言数据时碰到了一个挺头疼的问题,折腾半天终于解决了,把整个过程分享给大家:
splitted是我用split()函数对主数据框拆分后得到的data frame列表。拆分完成后,我想给列表里的每个data frame应用自定义函数,提取客户相关的统计信息。
我的自定义函数
这个函数用来从单个客户的交易数据里提取汇总信息,代码如下:
getCustomer <- function(df, numberOfProducts = 3){ Gender <- unique(df$gender) Segment <- unique(df$Segment) Net_Discount <- sum(df$Discount * df$Sales) Number_of_Discounts <- sum(df$Discount>0) Customer.ID <- unique(df$Customer.ID) Sales <- sum(df$Sales) Profit <- sum(df$Profit) lat <- mean(df$lat) lon <- mean(df$lon) productsData <- df %>% arrange(Order.Date) %>% top_n(n =numberOfProducts) Products <- 0 Products_Category <- 0 Products_Order_Date <- 0 for (j in 1:numberOfProducts){ Products[j] <- productsData %>% select(Product.ID) %>% filter(row_number()==j) Products_Category[j] <- productsData %>% select(Category) %>% filter(row_number()==j) Products_Order_Date[j] <- productsData %>% select(Order.Date) %>% filter(row_number()==j) names(Products)[j]<-paste("Product",j) names(Products_Category)[j]<-paste("Category Product",j) names(Products_Order_Date)[j]<-paste("Order Date Product",j) } output <- data.frame(Customer.ID, Gender,Segment, Net_Discount, Number_of_Discounts, Sales, Profit, Products, Products_Category, Products_Order_Date, lon,lat) return(output[1,]) }
尝试的操作与问题
一开始我测试单个元素,比如运行getCustomer(splitted[[687]],2),能得到正确结果;甚至手动逐个给customer列表赋值:
customer <- list() customer[[1]]<- getCustomer(splitted[[1]],2) customer[[2]]<- getCustomer(splitted[[2]],2) . . . customer[[1576]]<- getCustomer(splitted[[1576]],2)
这也完全没问题,但1576个元素手动处理效率太低了,于是我改用for循环批量处理:
customer <- list() for (i in 1:length(splitted)){ customer[[i]]<-getCustomer(splitted[[i]],2) }
结果运行后直接报错:
Error in data.frame(Customer.ID, Gender, Segment, Net_Discount, Number_of_Discounts, : arguments imply differing number of rows: 0, 1
我当时完全懵了——明明单个处理都正常,批量循环怎么就出问题了?
解决方案
后来仔细排查才发现,原来splitted列表里藏着3个空的data frame!当函数处理空数据框时,unique(df$Customer.ID)这类操作会返回长度为0的向量,而Net_Discount这类计算会返回长度为1的数值,组合成data frame时就会因为行数不匹配报错。
我用这段代码把空数据框删掉:
for (i in 1:length(splitted)){ l[i]<-nrow(splitted[[i]]) } indices<- which(l==0) splitted<-splitted[-indices]
删除这3个空数据框后,再运行之前的for循环就完全没问题了!
内容的提问来源于stack exchange,提问作者Andrės Acosta Escobar
相关产品推荐
相关产品推荐

