जियोमेट्रिक मीन: क्या कोई अंतर्निहित है?


106

मैंने ज्यामितीय माध्य के लिए बिल्ट-इन खोजने की कोशिश की, लेकिन नहीं कर सका।

(स्पष्ट रूप से एक अंतर्निहित कार्य शेल में काम करने के दौरान मुझे किसी भी समय बचाने के लिए नहीं जा रहा है, और न ही मुझे संदेह है कि सटीकता में कोई अंतर है। लिपियों के लिए मैं यथासंभव अंतर्निर्मित उपयोग करने की कोशिश करता हूं, जहां (संचयी) प्रदर्शन लाभ अक्सर ध्यान देने योग्य होता है।

मामले में यहाँ एक नहीं है (जो मुझे संदेह है कि मामला है) यहाँ मेरा है।

gm_mean = function(a){prod(a)^(1/length(a))}

11
नकारात्मक संख्याओं और अतिप्रवाह के बारे में सावधान। ठेस (ए) बहुत तेज़ी से कम या ज़्यादा हो जाएगी। मैंने इसे एक बड़ी सूची का उपयोग करके समय देने की कोशिश की और जल्दी से आपके विधि बनाम 1.4 का उपयोग करके Inf प्राप्त किया (एक्सप (माध्य (x))); गोलाई समस्या काफी गंभीर हो सकती है।
ट्रिस्टन

मैंने अभी फंक्शन को जल्दी से ऊपर लिखा क्योंकि मुझे यकीन था कि 5 मिनट इस क्यू को पोस्ट करने के बाद, कोई मुझे आर के बिल्ट-इन gm के बारे में बताएगा। इसलिए कोई अंतर्निहित नहीं है इसलिए यह निश्चित है कि आपकी टिप्पणियों के प्रकाश में फिर से कोड करने के लिए समय लगेगा। + 1 मुझसे।
doug

1
मैंने अभी 9 साल बाद इस जियोमेट्रिक-मीन और बिल्ट-इन को टैग किया था
स्मि

जवाबों:


78

यहाँ R में ज्यामितीय माध्य की गणना के लिए एक वेक्टर, शून्य- और NA- सहिष्णु फ़ंक्शन है। इसमें meanशामिल क्रियाओं की गणना length(x)उन मामलों के लिए आवश्यक है, जहाँ xगैर-सकारात्मक मान हैं।

gm_mean = function(x, na.rm=TRUE){
  exp(sum(log(x[x > 0]), na.rm=na.rm) / length(x))
}

na.rmपास-थ्रू नोटिंग के लिए @ बेन-बोल्कर और @Gregor को धन्यवाद कि यह सही ढंग से काम करता है।

मुझे लगता है कि कुछ टिप्पणियां NAडेटा और शून्य में मूल्यों के झूठ-तुल्यता से संबंधित हैं । आवेदन में मुझे ध्यान में था कि वे समान हैं, लेकिन निश्चित रूप से यह आम तौर पर सच नहीं है। इस प्रकार, यदि आप शून्य के वैकल्पिक प्रसार को शामिल करना चाहते हैं, और हटाने length(x)के मामले में अलग तरीके से व्यवहार करते हैं NA, तो निम्नलिखित फ़ंक्शन के लिए थोड़ा लंबा विकल्प है।

gm_mean = function(x, na.rm=TRUE, zero.propagate = FALSE){
  if(any(x < 0, na.rm = TRUE)){
    return(NaN)
  }
  if(zero.propagate){
    if(any(x == 0, na.rm = TRUE)){
      return(0)
    }
    exp(mean(log(x), na.rm = na.rm))
  } else {
    exp(sum(log(x[x > 0]), na.rm=na.rm) / length(x))
  }
}

ध्यान दें कि यह किसी भी नकारात्मक मूल्यों की जांच करता है, और अधिक जानकारीपूर्ण और उचित NaNसम्मान देता है कि ज्यामितीय माध्य नकारात्मक मानों के लिए परिभाषित नहीं है (लेकिन शून्य के लिए है)। टिप्पणीकारों के लिए धन्यवाद जो इस बारे में मेरे मामले पर रुके थे।


2
na.rmतर्क के रूप में गुजरना बेहतर नहीं होगा (यानी उपयोगकर्ता को यह तय करने दें कि वे एन-सहिष्णु होना चाहते हैं या नहीं, अन्य आर सारांश कार्यों के साथ संगतता के लिए)? मैं स्वतः ही शून्य को छोड़कर घबरा गया हूं - मैं इसे एक विकल्प भी बनाऊंगा।
बेन बोल्कर

1
शायद आप na.rmएक विकल्प के रूप में पास होने के बारे में सही हैं । मैं अपना जवाब अपडेट करूंगा। शून्य को छोड़कर, गैर-सकारात्मक मानों के लिए ज्यामितीय माध्य अनिर्दिष्ट है, जिसमें शून्य शामिल हैं। उपरोक्त ज्यामितीय माध्य के लिए एक सामान्य फिक्स है, जिसमें शून्य (या इस मामले में सभी गैर-शून्य) को 1 का डमी मूल्य दिया जाता है, जिसका उत्पाद पर कोई प्रभाव नहीं पड़ता है (या इसके विपरीत, लघुगणकीय योग में शून्य)।
पॉल मैकमुर्डी

* मेरा मतलब गैर-सकारात्मक मूल्यों के लिए एक सामान्य निर्धारण है, शून्य सबसे आम है जब ज्यामितीय माध्य का उपयोग किया जा रहा है।
पॉल मैकमर्डी 20

1
आपका na.rmपास-थ्रू कोडित के रूप में काम नहीं करता है ... देखें gm_mean(c(1:3, NA), na.rm = T)। आपको & !is.na(x)वेक्टर सबसेट से निकालने की आवश्यकता है , और चूंकि पहली आर्ग sumहै ..., इसलिए आपको na.rm = na.rmनाम से गुजरने की आवश्यकता है , और आपको कॉल में वेक्टर से 's 0' को बाहर करने की भी आवश्यकता है । NAlength
ग्रेगर थॉमस

2
खबरदार: xकेवल शून्य (एस) युक्त के लिए , जैसे x <- 0, ज्यामितीय माध्य के लिए exp(sum(log(x[x>0]), na.rm = TRUE)/length(x))देता 1है, जिसका कोई मतलब नहीं है।
१um

88

नहीं, लेकिन कुछ ही लोग हैं जिन्होंने एक लिखा है, जैसे कि यहाँ

इसका उपयोग करने के लिए एक और संभावना है:

exp(mean(log(x)))

ऍक्स्प (माध्य (x))) का उपयोग करने का एक और लाभ यह है कि आप बड़ी संख्याओं की लंबी सूची के साथ काम कर सकते हैं, जो कि अधिक स्पष्ट सूत्र का उपयोग करते समय समस्याग्रस्त है () का उपयोग करते हुए। ध्यान दें कि ठेस (a) ^ (1 / लंबाई (a)) और exp (माध्य (a)) एक ही उत्तर देते हैं।
ल्यूकहोलमैन

लिंक तय किया गया है
PatrickT

15

हम साइक पैकेज का उपयोग कर सकते हैं और जियोमेट्रिक.मेन फ़ंक्शन को कॉल कर सकते हैं ।


1
psych::geometric.mean()
22

इन कार्यों को श्रृंखला लेनी चाहिए और उनकी वृद्धि नहीं, कम से कम एक विकल्प के रूप में, मैं कहूंगा।
क्रिस्टोफ़ हनक

12

exp(mean(log(x)))

जब तक x में 0 न हो तब तक काम करेगा। यदि ऐसा है, तो लॉग-इन (-Infinite) का उत्पादन करेगा जो हमेशा 0 के ज्यामितीय माध्य में परिणामित होता है।

माध्य की गणना करने से पहले -In मान को हटाने का एक उपाय है:

geo_mean <- function(data) {
    log_data <- log(data)
    gm <- exp(mean(log_data[is.finite(log_data)]))
    return(gm)
}

आप ऐसा करने के लिए एक-लाइनर का उपयोग कर सकते हैं लेकिन इसका मतलब लॉग को दो बार गणना करना है जो अक्षम है।

exp(mean(log(i[is.finite(log(i))])))

जब आप कर सकते हैं तो दो बार लॉग की गणना क्यों करें: exp (माध्य (x [x! = 0]))
zzk

दोनों दृष्टिकोण गलत मतलब निकालते हैं, क्योंकि माध्य के लिए भाजक, sum(x) / length(x)गलत है यदि आप x को फ़िल्टर करते हैं और फिर इसे पास करते हैं mean
पॉल मैकमुर्डी

मुझे लगता है कि फ़िल्टरिंग एक बुरा विचार है जब तक कि आप स्पष्ट रूप से ऐसा करने का मतलब नहीं करते हैं (जैसे कि अगर मैं एक सामान्य-उद्देश्य फ़ंक्शन लिख रहा था तो मैं डिफ़ॉल्ट को फ़िल्टर नहीं करूंगा) - ठीक है अगर यह कोड का एक-बंद टुकड़ा है और आपने बहुत सावधानी से सोचा कि वास्तव में आपकी समस्या के संदर्भ में ज़ीरो को छानने का क्या मतलब है (!)
बेन बोल्कर

परिभाषा के अनुसार शून्य वाले संख्याओं का एक ज्यामितीय माध्य शून्य होना चाहिए! math.stackexchange.com/a/91445/221143
क्रिस

6

मैं ठीक वही उपयोग करता हूं जो मार्क कहता है। इस तरह, टॅापली के साथ भी, आप बिल्ट-इन meanफ़ंक्शन का उपयोग कर सकते हैं, आपको परिभाषित करने की कोई आवश्यकता नहीं है! उदाहरण के लिए, डाटा-मूल्य के प्रति-समूह ज्यामितीय साधनों की गणना करने के लिए:

exp(tapply(log(data$value), data$group, mean))

3

यह संस्करण अन्य उत्तरों की तुलना में अधिक विकल्प प्रदान करता है।

  • यह उपयोगकर्ता को उन परिणामों के बीच अंतर करने की अनुमति देता है जो (वास्तविक) संख्याएं नहीं हैं और जो उपलब्ध नहीं हैं। यदि ऋणात्मक संख्याएँ मौजूद हैं, तो उत्तर वास्तविक संख्या नहीं होगी, इसलिए NaNवापस कर दिया जाता है। यदि यह सभी NAमान है तो फ़ंक्शन यह NA_real_प्रतिबिंबित करने के बजाय वापस आ जाएगा कि एक वास्तविक मूल्य सचमुच उपलब्ध नहीं है। यह एक सूक्ष्म अंतर है, लेकिन एक है जो (थोड़ा) अधिक मजबूत परिणाम दे सकता है।

  • पहला वैकल्पिक पैरामीटर zero.rmउपयोगकर्ता को शून्य बनाने के बिना आउटपुट को प्रभावित करने की अनुमति देने के लिए है। तो zero.rmके लिए सेट है FALSEऔर etaकरने के लिए सेट कर दिया जाता NA_real_(उसके डिफ़ॉल्ट मान), शून्य से एक की ओर परिणाम सिकुड़ने का प्रभाव है। मेरे पास इसके लिए कोई सैद्धांतिक औचित्य नहीं है - यह सिर्फ शून्य को नजरअंदाज नहीं करने के लिए और कुछ करने के लिए समझ में आता है, लेकिन "कुछ करने के लिए" जो स्वचालित रूप से परिणाम शून्य बनाने को शामिल नहीं करता है।

  • etaशून्य से निपटने का एक तरीका है जो निम्नलिखित चर्चा से प्रेरित था: https://support.bioconSTR.org/p/64014/

geomean <- function(x,
                    zero.rm = TRUE,
                    na.rm = TRUE,
                    nan.rm = TRUE,
                    eta = NA_real_) {
    nan.count <- sum(is.nan(x))
     na.count <- sum(is.na(x))
  value.count <- if(zero.rm) sum(x[!is.na(x)] > 0) else sum(!is.na(x))

  #Handle cases when there are negative values, all values are missing, or
  #missing values are not tolerated.
  if ((nan.count > 0 & !nan.rm) | any(x < 0, na.rm = TRUE)) {
    return(NaN)
  }
  if ((na.count > 0 & !na.rm) | value.count == 0) {
    return(NA_real_)
  }

  #Handle cases when non-missing values are either all positive or all zero.
  #In these cases the eta parameter is irrelevant and therefore ignored.
  if (all(x > 0, na.rm = TRUE)) {
    return(exp(mean(log(x), na.rm = TRUE)))
  }
  if (all(x == 0, na.rm = TRUE)) {
    return(0)
  }

  #All remaining cases are cases when there are a mix of positive and zero
  #values.
  #By default, we do not use an artificial constant or propagate zeros.
  if (is.na(eta)) {
    return(exp(sum(log(x[x > 0]), na.rm = TRUE) / value.count))
  }
  if (eta > 0) {
    return(exp(mean(log(x + eta), na.rm = TRUE)) - eta)
  }
  return(0) #only propagate zeroes when eta is set to 0 (or less than 0)
}

1
क्या आप यह बताकर कुछ विवरण जोड़ सकते हैं कि यह मौजूदा समाधानों से कैसे भिन्न / सुधरता है? (मैं व्यक्तिगत रूप से dplyrइस तरह की उपयोगिता के लिए एक भारी निर्भरता नहीं जोड़ना चाहूंगा जब तक कि आवश्यक न हो ...)
बेन बोल्कर

मैं मानता हूं, case_whenएस थोड़ा मूर्ख थे, इसलिए मैंने उन्हें और ifएस के पक्ष में निर्भरता को हटा दिया । मैंने कुछ विस्तार भी दिए।
क्रिस कॉफी

1
मैं आपके बाद के विचार के साथ गया और तीनों `` `.rm`` मापदंडों को संरेखित nan.rmकरने के TRUEलिए डिफ़ॉल्ट को बदल दिया ।
क्रिस कॉफ़ी

1
एक अन्य शैलीगत नाइटिक। ifelseवैश्वीकरण के लिए बनाया गया है। जाँच करने के लिए एक ही शर्त के साथ, यह उपयोग करने के लिए अधिक मुहावरेदार होगाvalue.count <- if(zero.rm) sum(x[!is.na(x)] > 0) else sum(!is.na(x))
ग्रेग थॉमस

यह ifelseभी की तुलना में अच्छा लग रहा है। बदला हुआ। धन्यवाद!
क्रिस कॉफी


3

यदि आपके डेटा में मान नहीं है, तो यह एक दुर्लभ मामला नहीं है। आपको एक और तर्क जोड़ने की जरूरत है।

आप निम्नलिखित कोड आज़मा सकते हैं:

exp(mean(log(i[ is.finite(log(i)) ]), na.rm = TRUE))

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.