2014-10-06 13 views
6

में एकाधिक कॉलम को म्यूट करें मेरे पास ऐसा डेटा सेट है जो इस तरह दिखता है।डेटाफ्रेम

bankname bankid year totass cash bond loans 
Bank A  1  1881 244789 7250 20218 29513 
Bank B  2  1881 195755 10243 185151 2800 
Bank C  3  1881 107736 13357 177612 NA 
Bank D  4  1881 170600 35000 20000 5000 
Bank E  5  1881 3200000 351266 314012 NA 

और मैं बैंक बैलेंस शीट के आधार पर कुछ अनुपातों की गणना करना चाहता हूं। और मैं डाटासेट इस

bankname bankid year totass cash bond loans CashtoAsset BondtoAsset LoanstoAsset 
Bank A  1  1881 2447890 7250 202100 951300 0.002 0.082 0.388 
Bank B  2  1881 195755 10243 185151 2800 0.052 0.945 0.014 
Bank C  3  1881 107736 13357 177612 NA 0.123 1.648585431 NA 
Bank D  4  1881 170600 35000 20000 5000 0.205 0.117 0.029 
Bank E  5  1881 32000000 351266 314012 NA 0.0109 0.009 NA 

की तरह लग रहे करना चाहते हैं यहाँ डेटा

bankname <- c("Bank A","Bank B","Bank C","Bank D","Bank E") 
bankid <- c(1, 2, 3, 4, 5) 
year<- c(1881, 1881, 1881, 1881, 1881) 
totass <- c(244789, 195755, 107736, 170600, 32000000) 
cash<-c(7250,10243,13357,35000,351266) 
bond<-c(20218,185151,177612,20000,314012) 
loans<-c(29513,2800,NA,5000,NA) 
bankdata<-data.frame(bankname, bankid,year,totass, cash, bond, loans) 

पहले दोहराने के लिए कोड है, मैं बैलेंस शीट में NAS से छुटकारा मिला।

cols <- c("totass", "cash", "bond", "loans") 
bankdata[cols][is.na(bankdata[cols])] <- 0 

तब मैं अनुपात

library(dplyr) 
bankdata<-mutate(bankdata,CashtoAsset = cash/totass) 
bankdata<-mutate(bankdata,BondtoAsset = bond/totass) 
bankdata<-mutate(bankdata,loanstoAsset =loans/totass) 

लेकिन गणना, लाइन द्वारा कंप्यूटिंग इन सभी अनुपातों लाइन के बजाय, मैं इस बार में सभी ऐसा करने के लिए एक नज़र बनाना चाहते हैं। स्टेटटा में, मैं

foreach x of varlist cash bond loans { 
by bankid: gen `x'toAsset = `x'/ totass 
} 

मैं यह कैसे करूँगा?

+1

मेटा-टिप्पणी: जब दूसरे करने के लिए एक भाषा से अनुवाद करते समय, आप नहीं भी शाब्दिक होना जरूरत है। स्टाटा में लूप्स अक्सर आर में सरणी-आधारित गणना के रूप में बेहतर काम करते हैं (यहां तक ​​कि बातचीत भी सच हो सकती है: अन्य भाषाओं से स्टाटा के लिए नए आने वाले अक्सर अवलोकनों पर लूप का प्रयास करते हैं, जिन्हें शायद ही कभी जरूरी है।) –

+0

मैं यहां अपने चर को सरल बना देता हूं, लेकिन मेरे डेटासेट, मेरे पास संपत्तियों की 20 से अधिक श्रेणियां हैं, इसलिए लूप होने में सहायक है। –

+0

मेरे पास लूप के खिलाफ कुछ भी नहीं है; इसी तरह सामान्य आर उपयोगकर्ता निश्चित रूप से 20 कॉलम से खुश है .... –

उत्तर

0

आप इसे आवश्यक से थोड़ा कठिन बना सकते हैं। बस इसे आज़माएं और देखें कि क्या आपको इसकी आवश्यकता होती है।

bankdata$CashtoAsset <- bankdata$cash/bankdata$totass 
bankdata$BondtoAsset <- bankdata$bond/bankdata$totass 
bankdata$loantoAsset <- bankdata$loans/bankdata$totass 
bankdata 

इस पैदावार:

bankname bankid year totass cash bond loans CashtoAsset BondtoAsset loantoAsset 
1 Bank A  1 1881 244789 7250 20218 29513 0.02961734 0.082593581 0.12056506 
2 Bank B  2 1881 195755 10243 185151 2800 0.05232561 0.945830247 0.01430359 
3 Bank C  3 1881 107736 13357 177612  0 0.12397899 1.648585431 0.00000 
4 Bank D  4 1881 170600 35000 20000 5000 0.20515826 0.117233294 0.02930832 
5 Bank E  5 1881 32000000 351266 314012  0 0.01097706 0.009812875 0.00000000 

यह मिलना चाहिए आप सही दिशा में शुरू कर दिया।

0

यह dplyr की बड़ी कमियां में से एक है: जहाँ तक मुझे पता है हूँ, वहाँ दु: खद eval(parse(text=foo)) मुहावरा की तरह "हैक" किसी तरह का बिना प्रोग्राम के रूप में नहीं बल्कि सहभागी की तुलना में यह उपयोग करने के लिए कोई सीधा रास्ता है।

सबसे सरल दृष्टिकोण स्टाटा विधि जैसा ही है, लेकिन स्ट्रिंग मैनिपुलेशन स्टैट (या किसी अन्य स्क्रिप्टिंग भाषा में, उस मामले के लिए) में आर में थोड़ा अधिक वर्बोज़ है।

for (x in c("cash", "bond", "loans")) { 
    bankdata[sprintf("%stoAsset", x)] <- bankdata[x]/bankdata$totass # or, equivalently, bankdata["totass"] for a consistent "look" 
    ## can also replace `sprintf("%stoAsset", x)` with `paste0(c(x, "toAsset"))` or even `paste(x, "toAsset", collapse="") depending on what makes more sense to you. 
} 

पूरी बात अधिक Stata की तरह बनाने के लिए, तुम इतनी तरह within में पूरी बात लपेट कर सकते हैं:

bankdata <- within(bankdata, for (x in c("cash", "bond", "loans")) { 
    assign(x, get(x)/totass) 
}) 

लेकिन इस get और assign कार्य करता है जो नहीं कर रहे हैं के साथ कुछ हैकिंग जरूरत पर जोर देता सामान्य रूप से उपयोग करने के लिए सुरक्षित, हालांकि आपके मामले में यह शायद एक बड़ा सौदा नहीं है। उदाहरण के लिए, dplyr के साथ समान चाल की कोशिश करने की सलाह नहीं दी जाएगी, क्योंकि dplyr आर की गैर-मानक मूल्यांकन सुविधाओं का दुरुपयोग करता है और यह संभवतः इसके लायक होने की तुलना में अधिक परेशानी है। एक तेज और शायद बेहतर समाधान के लिए, data.table पैकेज देखें जो (मुझे लगता है) आपको स्टेटा-जैसे लूपिंग सिंटैक्स का उपयोग करने की अनुमति देगा, लेकिन dplyr की गति के साथ। सीआरएएन पर पैकेज विग्नेट देखें।

इसके अलावा, क्या आप वाकई वाकई NA प्रविष्टियों को फिर से सौंपना चाहते हैं? (दिसंबर के 2 का, 2017 के रूप में)

14

अद्यतन

जब से मैं इस सवाल का जवाब, मुझे एहसास हुआ है कि कुछ अतः उपयोगकर्ताओं को इस जवाब की जाँच की है।तब से dplyr पैकेज बदल गया है। इसलिए, मैं निम्नलिखित अद्यतन छोड़ देता हूं। मुझे उम्मीद है कि यह कुछ आर उपयोगकर्ताओं को mutate_at() का उपयोग करने के तरीके सीखने में मदद करेगा।

mutate_each() अब बहिष्कृत है। आप इसके बजाए mutate_at() का उपयोग करना चाहते हैं। आप निर्दिष्ट कर सकते हैं कि आप कौन से कॉलम .vars में अपना फ़ंक्शन लागू करना चाहते हैं। एक तरीका है vars() का उपयोग करना। दूसरा एक स्तंभ वेक्टर युक्त वर्ण वेक्टर का उपयोग करना है, जिसे आप .fun में अपना कस्टम फ़ंक्शन लागू करना चाहते हैं। दूसरा नंबरों के साथ कॉलम निर्दिष्ट करना है (उदाहरण के लिए, इस मामले में 5: 7)। ध्यान दें कि, यदि आप group_by() के लिए कॉलम का उपयोग करते हैं, तो आपको कॉलम स्थितियों की संख्या बदलने की आवश्यकता है। this question का एक नज़र डालें।

bankdata %>% 
mutate_at(.funs = funs(toAsset = ./totass), .vars = vars(cash:loans)) 

bankdata %>% 
mutate_at(.funs = funs(toAsset = ./totass), .vars = c("cash", "bond", "loans")) 

bankdata %>% 
mutate_at(.funs = funs(toAsset = ./totass), .vars = 5:7) 

# bankname bankid year totass cash bond loans cash_toAsset bond_toAsset loans_toAsset 
#1 Bank A  1 1881 244789 7250 20218 29513 0.02961734 0.082593581 0.12056506 
#2 Bank B  2 1881 195755 10243 185151 2800 0.05232561 0.945830247 0.01430359 
#3 Bank C  3 1881 107736 13357 177612 NA 0.12397899 1.648585431   NA 
#4 Bank D  4 1881 170600 35000 20000 5000 0.20515826 0.117233294 0.02930832 
#5 Bank E  5 1881 32000000 351266 314012 NA 0.01097706 0.009812875   NA 

मैं जानबूझकर .fun में कस्टम कार्य करने के लिए toAsset दिया क्योंकि यह मेरे में मदद मिलेगी नई स्तंभ नाम की व्यवस्था करने के। पहले, मैंने rename() का उपयोग किया था। लेकिन मुझे लगता है कि वर्तमान दृष्टिकोण में gsub() के साथ कॉलम नामों को साफ करना बहुत आसान है। यदि उपरोक्त परिणाम out के रूप में सहेजा गया है, तो आप कॉलम नामों में _ को निकालने के लिए निम्न कोड को चलाने के लिए चाहते हैं।

names(out) <- gsub(names(out), pattern = "_", replacement = "") 

मूल जवाब

मुझे लगता है कि आप dplyr साथ इस तरह से कुछ टाइपिंग बचा सकता है। नकारात्मकता आप नकदी, बंधन और ऋण को ओवरराइट करते हैं।

bankdata %>% 
    group_by(bankname) %>% 
    mutate_each(funs(whatever = ./totass), cash:loans) 

# bankname bankid year totass  cash  bond  loans 
#1 Bank A  1 1881 244789 0.02961734 0.082593581 0.12056506 
#2 Bank B  2 1881 195755 0.05232561 0.945830247 0.01430359 
#3 Bank C  3 1881 107736 0.12397899 1.648585431   NA 
#4 Bank D  4 1881 170600 0.20515826 0.117233294 0.02930832 
#5 Bank E  5 1881 32000000 0.01097706 0.009812875   NA 

यदि आप अपने अपेक्षित परिणाम पसंद करते हैं, तो मुझे लगता है कि कुछ टाइपिंग आवश्यक है। नामकरण हिस्सा ऐसा कुछ प्रतीत होता है जो आपको करना होगा।

bankdata %>% 
    group_by(bankname) %>% 
    summarise_each(funs(whatever = ./totass), cash:loans) %>% 
    rename(cashtoAsset = cash, bondtoAsset = bond, loanstoAsset = loans) -> ana; 
    ana %>% 
    merge(bankdata,., by = "bankname") 

# bankname bankid year totass cash bond loans cashtoAsset bondtoAsset loanstoAsset 
#1 Bank A  1 1881 244789 7250 20218 29513 0.02961734 0.082593581 0.12056506 
#2 Bank B  2 1881 195755 10243 185151 2800 0.05232561 0.945830247 0.01430359 
#3 Bank C  3 1881 107736 13357 177612 NA 0.12397899 1.648585431   NA 
#4 Bank D  4 1881 170600 35000 20000 5000 0.20515826 0.117233294 0.02930832 
#5 Bank E  5 1881 32000000 351266 314012 NA 0.01097706 0.009812875   NA 
+0

हाय, मैं यहां पोस्ट किए गए सभी अलग-अलग विकल्पों की कोशिश कर रहा हूं। जब मैंने आपके कोड की कोशिश की, तो मुझे मिल गया। 'त्रुटि: ऑब्जेक्ट 'एना' नहीं मिला। क्या आप मुझे समझाएंगे कि क्या हो रहा है? धन्यवाद। –

+0

@ एचपीर्क मैं पाइपिंग प्रक्रिया में वस्तु, एना को आउटपुट सौंप रहा हूं। यदि यह दृष्टिकोण आपके लिए काम नहीं करता है, तो आप कर सकते हैं, 'एना <- बैंकडेटा%>% group_by (बैंकनाम)%>% summarise_each (मज़ेदार (जो भी = ./totass), नकदी: ऋण)%>% नाम बदलें (cashtoAsset = नकदी, bondtoAsset = बंधन, loanstoAsset = ऋण); एना%>% मर्ज (बैंकडाटा,।, द्वारा = "बैंक नाम") ' – jazzurro

0

प्रयास करें:

for(i in 5:7){ 
    bankdata[,(i+3)] = bankdata[,i]/bankdata[,4] 
} 
names(bankdata)[(5:7)+3] = paste0(names(bankdata)[5:7], 'toAssest') 

आउटपुट:

bankdata 
    bankname bankid year totass cash bond loans cashtoAssest bondtoAssest loanstoAssest 
1 Bank A  1 1881 244789 7250 20218 29513 0.02961734 0.082593581 0.12056506 
2 Bank B  2 1881 195755 10243 185151 2800 0.05232561 0.945830247 0.01430359 
3 Bank C  3 1881 107736 13357 177612  0 0.12397899 1.648585431 0.00000000 
4 Bank D  4 1881 170600 35000 20000 5000 0.20515826 0.117233294 0.02930832 
5 Bank E  5 1881 32000000 351266 314012  0 0.01097706 0.009812875 0.00000000 
2

यहाँ एक data.table समाधान है।

library(data.table) 
setDT(bankdata) 
bankdata[, paste0(names(bankdata)[5:7], "toAsset") := 
      lapply(.SD, function(x) x/totass), .SDcols=5:7] 
bankdata 
# bankname bankid year totass cash bond loans cashtoAsset bondtoAsset loanstoAsset 
# 1: Bank A  1 1881 244789 7250 20218 29513 0.02961734 0.082593581 0.12056506 
# 2: Bank B  2 1881 195755 10243 185151 2800 0.05232561 0.945830247 0.01430359 
# 3: Bank C  3 1881 107736 13357 177612  0 0.12397899 1.648585431 0.00000000 
# 4: Bank D  4 1881 170600 35000 20000 5000 0.20515826 0.117233294 0.02930832 
# 5: Bank E  5 1881 32000000 351266 314012  0 0.01097706 0.009812875 0.00000000 
2

Apply और cbind

cbind(bankdata,apply(bankdata[,5:7],2, function(x) x/bankdata$totass)) 
names(bankdata)[8:10] <- paste0(names(bankdata)[5:7], 'toAssest’) 

> bankdata 
    bankname bankid year totass cash bond loans cashtoAssest bondtoAssest loanstoAssest 
1 Bank A  1 1881 244789 7250 20218 29513 0.02961734 0.082593581 0.12056506 
2 Bank B  2 1881 195755 10243 185151 2800 0.05232561 0.945830247 0.01430359 
3 Bank C  3 1881 107736 13357 177612 NA 0.12397899 1.648585431   NA 
4 Bank D  4 1881 170600 35000 20000 5000 0.20515826 0.117233294 0.02930832 
5 Bank E  5 1881 32000000 351266 314012 NA 0.01097706 0.009812875   NA