从R中的data.frame创建新类

时间:2016-11-14 17:40:38

标签: r

我正在玩弄R中的函数,类和方法。 为了进行一次有用的“亲自动手”练习,我决定创建一个“套餐”来照顾我的家庭预算。 简单地说,我想要一系列函数,类和方法来计算东西,绘制不同类型的图表,什么不是。 我想要做的第一件事就是创建一个“预算”类:这应该包含一个带有某些列的csv并返回一个对象“Budget”,该对象继承了数据框的相同方法,但我可以向其应用一组“预算”方法。 这是我的看法

prepareData = function (csv, type=1) {

if (type == 1) {
Data = read.csv(csv,dec = ".")}
else if (type == 2) {
Data = read.csv2(csv,dec = ",")}
else {stop ("Accetable value for type are 1 and 2")}

NamesToHave = c("Date","Title","Amount","Category")

if (sum(as.numeric(colnames(Data) %in% NamesToHave)) < 4) {
    stop ("The csv file has not the mandatory columns (Data, Title, Amount, Category)")}




if (class(try(tolower(Data$Title),silent = T)) == "try-error" | class(try(tolower(Data$Category),silent = T)) == "try-error") {
    stop("Are you sure there are no special character in your csv file ?")} 

Data$Day = sapply(strsplit(as.character(Data$Date), "/"),"[[",1)
Data$Month = month.abb[as.numeric(sapply(strsplit(as.character(Data$Date), "/"),"[[",2))]
Data$Year = sapply(strsplit(as.character(Data$Date), "/"),"[[",3)

Data = Data[with(Data, order(Year, Month, Day)), ]
Data$Amount = as.character(Data$Amount)
Data$Amount = as.numeric(as.character(Data$Amount))

class(Data) <- append(class(Data),"Budget")
return(Data)
}

现在,这会返回一个包含所有必要修改的数据框,总体来说它作为一个函数可以正常工作,但如果我按照以下方式使用csv

structure(list(Date = structure(c(22L, 1L, 1L, 1L, 1L, 1L), .Label = c("01/10/2016", 
"01/11/2016", "02/10/2016", "04/10/2016", "04/11/2016", "05/10/2016", 
"05/11/2016", "06/10/2016", "06/11/2016", "07/10/2016", "08/10/2016", 
"08/11/2016", "09/10/2016", "09/11/2016", "10/10/2016", "10/11/2016", 
"11/10/2016", "12/11/2016", "14/10/2016", "16/10/2016", "18/10/2016", 
"20/09/2016", "20/10/2016", "21/10/2016", "22/09/2016", "22/10/2016", 
"23/09/2016", "23/10/2016", "25/09/2016", "25/10/2016", "26/09/2016", 
"26/10/2016", "27/10/2016", "28/10/2016", "29/10/2016", "30/10/2016"
), class = "factor"), Title = structure(c(20L, 6L, 36L, 29L, 
30L, 11L), .Label = c("Bagpiper", "beer debaser", "Br", "brewdog", 
"Burger King", "Clas", "coop", "Coop", "Eriksdalbadet", "etc", 
"ETC", "Flippin", "Fotografiska", "Gateau Agneta", "Grekisk fastfood", 
"Grill", "Gunnarson", "Gunnarsson", "hemkop", "HK", "Hotorhallen", 
"ICA", "ICA Skinnskat", "Igor Sport", "Intersport", "Kak", "klattercentret", 
"LullesFagel", "Mae Thai", "MamaWolf", "Material", "Matrerial", 
"Oriental Supermarket", "Paradiset", "Pendeltag Uppsala", "PGW", 
"Pressbyran", "Primeburger", "Primo Ciao ciao", "R Asia", "Systembolaget", 
"taxi Skinnskat", "The Cure drinks", "Udden pensionat", "Ugglan", 
"Wentzels hobby"), class = "factor"), Amount = c(167.27, 331, 
971, 99, 192, 3289), Category = structure(c(10L, 3L, 3L, 6L, 
6L, 3L), .Label = c("Drink", "extra", "Extra", "Extra_Fede", 
"extra_food", "Extra_food", "extra_laure", "Extra_Laure", "food", 
"Food"), class = "factor")), .Names = c("Date", "Title", "Amount", 
"Category"), row.names = c(NA, 6L), class = "data.frame")

我跑

Data = prepareData("name.csv")
class(Data)

输出只是“data.frame”。但是如果我再从终端再次运行函数的第二行到最后一行

class(Data) <- append(class(Data),"Budget")
class(Data)

我将“data.frame”和“Budget”作为输出。

我做错了什么?

1 个答案:

答案 0 :(得分:2)

你的问题在这里:

if (as.numeric(colnames(Data) %in% NamesToHave) != 4) {}

第一次比较将进行矢量化并返回TRUE TRUE TRUE TRUE,当抛出1 1 1 1时将变为as.numeric()。然后,将该矢量与!= 4进行比较,TRUE TRUE TRUE TRUE执行矢量化并返回as.numeric()(所有'一个与四个不同)。 if()`语句不会评估整个向量,只是它的第一个元素(并给你一个警告信息)。

要解决此问题,您只需将sum()功能切换为if (sum(colnames(Data) %in% NamesToHave) != 4) {} 即可。

R

当您对逻辑向量求和时,TRUE会将其强制为数字:所有1变为FASLE,所有0变为FALSE。现在,您将获得在if语句中评估R的4个和,以及它顺利运行的函数。一旦我解决了它,它在我第一次运行时就有两个类。

正如this article中所述,在发布问题之前重新启动(?!\bi+\b)\b[dcmlxvi]+\b|(\bi+\.) 并确保您仍然遇到报告问题是很好的。