2016-11-14 86 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

好吧,明白了。 感謝您的反饋! –