2016-11-14 46 views
3

我在R中使用函数,类和方法。 要进行“手动”练习也可能有用,我决定创建我的“包”照顾我的家庭预算。 简而言之,我想要一系列函数,类和方法来计算东西,绘制不同类型的图表,哪些不是。 我想要做的第一件事就是创建一个“Budget”类:它应该带有某些列的csv,并返回一个对象“Budget”,它继承了数据框的相同方法,但是我可以将其应用于一组“预算”方法。 这是我拿从R中的data.frame创建新的类

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”和“预算”作为输出。

我在做什么错?

+0

我无法重现您的问题,因为您发布的示例有几个问题。请看看[这篇文章](http://stackoverflow.com/help/mcve)。 –

+0

我也无法重现您的问题,该对象似乎同时具有正确的类。 –

+0

奇怪的是,我知道,当我修复了一个不相关的问题时(请参阅下面的答案),问题就会得到解决。正如Tomas所说,有时候重新启动R可能会有所帮助。 –

回答

2

你的问题在这里:

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

第一比较 - 将矢量执行和返回TRUE TRUE TRUE TRUE,走的时候扔as.numeric()这将成为1 1 1 1。然后,这个向量将被比较为!= 4,这是矢量化执行并返回TRUE TRUE TRUE TRUE(所有的'不同于四')。 if()`语句不会评估整个向量,只是它的第一个元素(并且会引发一条警告消息)。

要解决此问题,您只需将as.numeric()函数切换为sum()

if (sum(colnames(Data) %in% NamesToHave) != 4) {} 

当你总结的逻辑向量,R将它强制给数值:所有TRUE成为1和所有FASLE成为0。现在,您将拥有4条将在if语句中评估FALSE的总和以及它运行平稳的功能。一旦我解决了它,当我第一次运行它时,它就有两个类。

正如this article所述,在发布您的问题之前重新启动R并确保您仍然存在您要报告的问题。

+0

谢谢,我正在纠正我的例子时发现了同样的事情。 然而,作为一种后续行动和一种改善自我的方式:您认为这是一个最小可重现的例子,缺乏什么? 我把数据和代码放进去了,我可以做些什么更好的? 无论如何,再次感谢! –

+0

我们不需要知道你在函数本身之前处理的每个案例(所有那些在开始的时候是否是else)。事实上,如果您在发布问题之前将它们取消了,您会意识到问题不在于分配类,而是处理可能的错误。 –

+0

好吧,明白了。 感谢您的反馈! –