कैसे (आर में) तार के दो वैक्टर मैच के लिए अर्ध?


36

मुझे यकीन नहीं है कि इसे कैसे समाप्त किया जाना चाहिए, इसलिए यदि आप बेहतर शब्द जानते हैं तो कृपया मुझे सही करें।

मुझे दो सूचियाँ मिली हैं। 55 वस्तुओं में से एक (जैसे: तार का एक सदिश), 92 का दूसरा। आइटम नाम समान हैं, लेकिन समान नहीं हैं।

मैं सबसे अच्छा उम्मीदवार खोजने के लिए इच्छा रों 55 सूची में आइटम्स (मैं तो इसके माध्यम से जाने के लिए और सही फिटिंग ले जाएगा) के लिए 92 की सूची में।

यह कैसे किया जा सकता है?

मेरे पास जहां विचार थे:

  1. मैच देखने वाले सभी देखें (किसी सूची का उपयोग करके? मिलान)
  2. स्ट्रिंग्स वैक्टर के बीच एक दूरी मैट्रिक्स का प्रयास करें, लेकिन मुझे यकीन नहीं है कि इसे कैसे परिभाषित किया जाए (समान अक्षरों की संख्या, स्ट्रिंग्स के आदेश के बारे में क्या?)

तो क्या पैकेज / कार्य / क्षेत्र-अनुसंधान इस तरह के कार्य से संबंधित है, और कैसे?

अपडेट: यहां वेक्टर्स का एक उदाहरण है जो मैं मैच करना चाहता हूं

vec55 <- c("Aeropyrum pernix", "Archaeoglobus fulgidus", "Candidatus_Korarchaeum_cryptofilum", 
"Candidatus_Methanoregula_boonei_6A8", "Cenarchaeum_symbiosum", 
"Desulfurococcus_kamchatkensis", "Ferroplasma acidarmanus", "Haloarcula_marismortui_ATCC_43049", 
"Halobacterium sp.", "Halobacterium_salinarum_R1", "Haloferax volcanii", 
"Haloquadratum_walsbyi", "Hyperthermus_butylicus", "Ignicoccus_hospitalis_KIN4", 
"Metallosphaera_sedula_DSM_5348", "Methanobacterium thermautotrophicus", 
"Methanobrevibacter_smithii_ATCC_35061", "Methanococcoides_burtonii_DSM_6242"
)
vec91 <- c("Acidilobus saccharovorans 345-15", "Aciduliprofundum boonei T469", 
"Aeropyrum pernix K1", "Archaeoglobus fulgidus DSM 4304", "Archaeoglobus profundus DSM 5631", 
"Caldivirga maquilingensis IC-167", "Candidatus Korarchaeum cryptofilum OPF8", 
"Candidatus Methanoregula boonei 6A8", "Cenarchaeum symbiosum A", 
"Desulfurococcus kamchatkensis 1221n", "Ferroglobus placidus DSM 10642", 
"Halalkalicoccus jeotgali B3", "Haloarcula marismortui ATCC 43049", 
"Halobacterium salinarum R1", "Halobacterium sp. NRC-1", "Haloferax volcanii DS2", 
"Halomicrobium mukohataei DSM 12286", "Haloquadratum walsbyi DSM 16790", 
"Halorhabdus utahensis DSM 12940", "Halorubrum lacusprofundi ATCC 49239", 
"Haloterrigena turkmenica DSM 5511", "Hyperthermus butylicus DSM 5456", 
"Ignicoccus hospitalis KIN4/I", "Ignisphaera aggregans DSM 17230", 
"Metallosphaera sedula DSM 5348", "Methanobrevibacter ruminantium M1", 
"Methanobrevibacter smithii ATCC 35061", "Methanocaldococcus fervens AG86", 
"Methanocaldococcus infernus ME", "Methanocaldococcus jannaschii DSM 2661", 
"Methanocaldococcus sp. FS406-22", "Methanocaldococcus vulcanius M7", 
"Methanocella paludicola SANAE", "Methanococcoides burtonii DSM 6242", 
"Methanococcus aeolicus Nankai-3", "Methanococcus maripaludis C5", 
"Methanococcus maripaludis C6", "Methanococcus maripaludis C7", 
"Methanococcus maripaludis S2", "Methanococcus vannielii SB", 
"Methanococcus voltae A3", "Methanocorpusculum labreanum Z", 
"Methanoculleus marisnigri JR1", "Methanohalobium evestigatum Z-7303", 
"Methanohalophilus mahii DSM 5219", "Methanoplanus petrolearius DSM 11571", 
"Methanopyrus kandleri AV19", "Methanosaeta thermophila PT", 
"Methanosarcina acetivorans C2A", "Methanosarcina barkeri str. Fusaro", 
"Methanosarcina mazei Go1", "Methanosphaera stadtmanae DSM 3091", 
"Methanosphaerula palustris E1-9c", "Methanospirillum hungatei JF-1", 
"Methanothermobacter marburgensis str. Marburg", "Methanothermobacter thermautotrophicus str. Delta H", 
"Nanoarchaeum equitans Kin4-M", "Natrialba magadii ATCC 43099", 
"Natronomonas pharaonis DSM 2160", "Nitrosopumilus maritimus SCM1", 
"Picrophilus torridus DSM 9790", "Pyrobaculum aerophilum str. IM2", 
"Pyrobaculum arsenaticum DSM 13514", "Pyrobaculum calidifontis JCM 11548", 
"Pyrobaculum islandicum DSM 4184", "Pyrococcus abyssi GE5", "Pyrococcus furiosus DSM 3638", 
"Pyrococcus horikoshii OT3", "Staphylothermus hellenicus DSM 12710", 
"Staphylothermus marinus F1", "Sulfolobus acidocaldarius DSM 639", 
"Sulfolobus islandicus L.D.8.5", "Sulfolobus islandicus L.S.2.15", 
"Sulfolobus islandicus M.14.25", "Sulfolobus islandicus M.16.27", 
"Sulfolobus islandicus M.16.4", "Sulfolobus islandicus Y.G.57.14", 
"Sulfolobus islandicus Y.N.15.51", "Sulfolobus solfataricus P2", 
"Sulfolobus tokodaii str. 7", "Thermococcus gammatolerans EJ3", 
"Thermococcus kodakarensis KOD1", "Thermococcus onnurineus NA1", 
"Thermococcus sibiricus MM 739", "Thermofilum pendens Hrk 5", 
"Thermoplasma acidophilum DSM 1728", "Thermoplasma volcanium GSS1", 
"Thermoproteus neutrophilus V24Sta", "Thermosphaera aggregans DSM 11486", 
"Vulcanisaeta distributa DSM 14429", "uncultured methanogenic archaeon RC-I"
) 

2
हाय ताल:> यह देखते हुए कि ये टाइपो-मुक्त वैज्ञानिक नाम हैं, मैं पहले लेवेंसहाइट मीट्रिक की कोशिश करूँगा (92-बाय -55 डिस्टेंस मैट्रिक्स के संदर्भ में) और देखें कि यह कैसे निकलता है।
user603

2
कुछ समय बाद, stringdistपैकेज इस तरह की चीज़ के लिए सबसे अच्छा संसाधन लगता है।
shabbychef

जवाबों:


19

मुझे भी ऐसी ही समस्याएँ हैं। (यहां देखा गया: https://stackoverflow.com/questions/2231993/merging-two-data-frames-using-fuzzy-approximate-string-matching-in-r )

मेरे द्वारा प्राप्त की गई अधिकांश सिफारिशें:

pmatch(), और agrep(), grep(), grepl()तीन कार्य हैं कि यदि आप समय लेने के लिए के माध्यम से देखने के लिए अनुमानित स्ट्रिंग या अनुमानित रेगुलर एक्सप्रेशन द्वारा या तो लगभग स्ट्रिंग मिलान में कुछ अंतर्दृष्टि के साथ प्रदान करेगा।

स्ट्रिंग्स को देखे बिना, आपको उनका मिलान कैसे करना है, इसका कठिन उदाहरण प्रदान करना कठिन है। यदि आप हमें कुछ उदाहरण डेटा प्रदान कर सकते हैं तो मुझे यकीन है कि हम एक समाधान के लिए आ सकते हैं।

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

क्या हम उन्हें देख सकते हैं?

अद्यतन करें

ऐसा लगता है कि agrep () इनमें से अधिकांश के लिए ट्रिक करेगा। ध्यान दें कि agrep () Levenshtein दूरी के R का कार्यान्वयन है।

agrep(vec55[1],vec91,value=T)

कुछ गणना नहीं है, हालांकि, मुझे भी यकीन नहीं है कि फेरोप्लाज्म एसिडारामस फेरोग्लोबस प्लेसिडस डीएसएम 10642 के समान है, उदाहरण के लिए:

agrep(vec55[7],vec91,value=T) 

मुझे लगता है कि आप इनमें से कुछ के लिए थोड़ा SOL हो सकते हैं और शायद स्क्रैच से इंडेक्स बनाना सबसे अच्छा दांव है। अर्थात,। Vec55 के लिए आईडी संख्याओं के साथ एक तालिका बनाएं, और फिर मैन्युअल रूप से आईडी के vec55 में vec91 में एक संदर्भ बनाएं। दर्दनाक, मुझे पता है, लेकिन यह बहुत कुछ agrep () के साथ किया जा सकता है।


हाय ब्रैंडन - मैंने डेटा का एक नमूना जोड़ा। धन्यवाद!
ताल गलिली

हाय ब्रैंडन - आपके समाधान ने बहुत काम किया - धन्यवाद।
ताल गलिली

एसई में विषय पर पिछले प्रश्न के लिंक के लिए +1 (सूचक को एग्रेप () के लिए थाक्स)।
user603

15

दो तारों के बीच की दूरी को मापने के कई तरीके हैं। आर में व्यापक रूप से लागू किए गए दो महत्वपूर्ण (मानक) दृष्टिकोण लेवेनशेटिन और हैमिंग दूरी हैं। पूर्व पैकेज 'मेंटलस्पीको' में उपलब्ध है और बाद में 'ई 1071' में उपलब्ध है। इनका उपयोग करते हुए, मैं बस ९ ३ को ५५ मैट्रिक्स की जोड़ीदार दूरियों से गणना करूँगा, फिर वहां से आगे बढ़ना होगा (अर्थात सूची १ में स्ट्रिंग "१" के लिए सबसे अच्छा उम्मीदवार मैच सूची २ से स्ट्रिंग "x" है) ")।

वैकल्पिक रूप से, पैकेज में एक फ़ंक्शन तुलना () होती है रिकॉर्डलिंक जो कि आप जो चाहते हैं उसे करने के लिए डिज़ाइन किया गया लगता है और तथाकथित Jaro-Winkler दूरी का उपयोग करता है जो हाथ में कार्य के लिए अधिक उपयुक्त लगता है, लेकिन मुझे इसके साथ कोई अनुभव नहीं था ।

संपादित करें: मैं अपने प्रश्न को संपादित कर रहा हूँ ब्रैंडन की टिप्पणी के साथ ही ताल के कोड, करने के लिए "Aeropyrum pernix" एक मैच खोजने के लिए, की पहली प्रविष्टि शामिल करने के लिए vec55 :

agrep(vec55[1],vec91,ignore.case=T,value=T,max.distance = 0.1, useBytes = FALSE)
[1] "Aeropyrum pernix K1"

8
+1। इसके अलावा, यदि यह मददगार है, तो स्ट्रिंग्स की तुलना करने पर Google का शब्द "एडिट डिस्टेंस" है: en.wikipedia.org/wiki/Edit_distance
ars

@ars:> धन्यवाद, कि आर सर्च इंजन को खिलाने के लिए एक आसान सूची है और देखें कि क्या निकलता है!
user603

2
लेवेनशेन एडिट दूरी को एग्रीप () के माध्यम से बेस पैकेज के हिस्से के रूप में कार्यान्वित किया जाता है
ब्रैंडन

महान जवाब Kwak - मैं भविष्य में इस पर एक नज़र होगा!
ताल गलिली

निजी तौर पर, मुझे लगता है कि यह ताल के सवाल का एक अधिक संपूर्ण जवाब है। +1 हमारे रिकॉर्डलिंक को इंगित करने के लिए - मुझे निश्चित रूप से इसे आज़माना होगा।
ब्रैंडन बर्टेल्सन

7

क्वाक के उपयोगी उत्तर के पूरक के लिए, मुझे कुछ सरल सिद्धांतों और विचारों को जोड़ने की अनुमति दें। मीट्रिक निर्धारित करने का एक अच्छा तरीका यह विचार करना है कि तार उनके लक्ष्य से कैसे भिन्न हो सकते हैं। "एडिट डिस्टेंस" उपयोगी है, जब भिन्नता टाइपोग्राफिक त्रुटियों का एक संयोजन है जैसे पड़ोसियों को ट्रांसपोज़ करना या किसी एकल कुंजी को टाइप करना गलत है।

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


3

मैं आपको यह भी सुझाव दूंगा कि आप एन-ग्राम और दमरेउ-लेवेनशेटिन दूरी के अलावा किटक के अन्य सुझावों को भी देखें।

यह पत्र यहां उल्लिखित कुछ अलग-अलग संपादन दूरी की सटीकता की तुलना करता है (और इसे Google विद्वान के अनुसार अत्यधिक उद्धृत किया गया है)।

जैसा कि आप देख सकते हैं कि इस से संपर्क करने के कई अलग-अलग तरीके हैं, और आप अलग-अलग मैट्रिक्स को भी जोड़ सकते हैं। मुझे लगता है कि लेवेंसहाइट और संबंधित आधारित मैट्रिक्स सबसे सहज ज्ञान युक्त हैं, खासकर अगर मानव टाइपिंग के कारण त्रुटियां होती हैं। एन-ग्राम भी सरल हैं और डेटा के लिए समझ में आता है जो कि प्रति नाम या शब्द नहीं है।

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

मैं जहाँ तक पैकेज की मदद नहीं कर सकता, लेकिन एन-ग्राम की अवधारणा बहुत सरल है (मैंने हाल ही में एन-ग्राम करने के लिए एक एसपीएसएस मैक्रो बनाया था, लेकिन इस तरह के एक छोटे प्रोजेक्ट के लिए मैं पहले से ही बनाए गए पैकेजों के साथ जाऊंगा अन्य पोस्टरों ने सुझाव दिया है)। यहां अजगर में लेवेंसाइटिन दूरी की गणना करने का एक उदाहरण है।


धन्यवाद एंडी - मैं भविष्य में इस पर एक नज़र डालूंगा।
ताल गलिली

1

मैंने कुछ पैकेजों और तरीकों पर शोध किया कि इस समस्या को कैसे हल किया जाए और मुझे लगता है कि सबसे अच्छा उम्मीदवार fuzzywuzzyRपैकेज है।

FuzzywuzzyR पैकेज का एक फजी स्ट्रिंग मिलान implemenation है fuzzywuzzy अजगर पैकेज। यह दृश्यों के बीच के अंतर की गणना करने के लिए लेवेंसहाइट डिस्टेंस का उपयोग करता है। FuzzywuzzyR की कार्यक्षमता के बारे में अधिक जानकारी ब्लॉग-पोस्ट और पैकेज विगनेट में पाई जा सकती है ।

मैंने आपकी समस्या का सरल समाधान किया, लेकिन थोड़ी पकड़ है। आपको अजगर को स्थापित करना होगा और यदि आप वाइनडोज़ का उपयोग करते हैं तो दृश्य स्टूडियो के लिए कुछ बिल्ड टूल भी स्थापित करने होंगे । आपको इन्हें चुनना होगा:

  • विंडोज 10 एसडीके 10.0.17763.0 और एमएसवीसी v140
  • वीएस 2015 सी ++ निर्माण उपकरण (v 14v00)

समाधान सरल है। मुख्य फ़ंक्शन ExtractOneदो मानों की सूची देता है। पहला एक स्ट्रिंग मैच है और दूसरा एक समान स्कोर (सीमा 0 - 100 में) है। fuzzywuzzyRपैकेज भी अन्य कार्य करता है जो उपयोगी हो सकता है प्रदान करता है। मुख्य दस्तावेज मिल सकते हैं यहाँ है । मुझे उम्मीद है कि यह कोड समस्या को हल करने में मदद करता है।

library(fuzzywuzzyR)

# The Fuzzy initialization
init_proc = FuzzUtils$new()
PROC = init_proc$Full_process # class process-method
PROC1 = tolower # base R function
init_scor = FuzzMatcher$new()
SCOR = init_scor$WRATIO    
init <- FuzzExtract$new()

match_strings <- function(vector_to_process, base_vector){  
  new_vec = c()
  for(i in 1:length(vector_to_process)){      
    new_word <- init$ExtractOne(string = vector_to_process[i], sequence_strings = base_vector, processor = PROC1, scorer = SCOR, score_cutoff = 0L)
    new_vec[i] <- new_word[[1]]
  }     
  return(new_vec)
}

# Check if all python modules are available
if (check_availability()){    
  new_vec <- match_strings(vec55, vec91)
  print(new_vec)   
}

आउटपुट:

[1] "Aeropyrum pernix K1"                                 "Archaeoglobus fulgidus DSM 4304"                    
[3] "Candidatus Korarchaeum cryptofilum OPF8"             "Candidatus Methanoregula boonei 6A8"                
[5] "Cenarchaeum symbiosum A"                             "Desulfurococcus kamchatkensis 1221n"                
[7] "Thermoplasma volcanium GSS1"                         "Haloarcula marismortui ATCC 43049"                  
[9] "Halobacterium sp. NRC-1"                             "Halobacterium salinarum R1"                         
[11] "Haloferax volcanii DS2"                              "Haloquadratum walsbyi DSM 16790"                    
[13] "Hyperthermus butylicus DSM 5456"                     "Ignicoccus hospitalis KIN4/I"                       
[15] "Metallosphaera sedula DSM 5348"                      "Methanothermobacter thermautotrophicus str. Delta H"
[17] "Methanobrevibacter smithii ATCC 35061"               "Methanococcoides burtonii DSM 6242"       

0

फ़ंक्शन के आधार पर adist

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

stringdistएक ही नाम के पैकेज से कार्य करने की कई विधियाँ हैं (देखें ?stringdist):

विधि = सी ("ओसा", "एलवी", "डीएल", "हैमिंग", "एलसीएस", "क्यूग्राम", "कोसाइन", "जैकार्ड", "जेवी", "साउंडेक्स")

इसके साथ, आप अधिकतम विचलन (दहलीज) का चयन कर सकते हैं:

firstvector<-vec55
secondvector<-vec91

match<-character()
threshold<-14 # max 14 characters of divergence
mindist<-integer()
sortedmatches<-character()

for (i in 1:length(firstvector) ) {
  matchdist<-adist(firstvector[i],secondvector)[1,]
  # matchdist<-stringdist(firstvector[i],secondvector) # several methods available

  matchdist<-ifelse(matchdist>threshold,NA,matchdist)
  sortedmatches[i]<-paste(secondvector[order(matchdist, na.last=NA)], collapse = ", ")
  mindist[i]<- tryCatch(ifelse(is.integer(which.min(matchdist)),matchdist[which.min(matchdist)],NA), error = function(e){NA})
  match[i]<-ifelse(length(secondvector[which.min(matchdist)])==0,NA,
                  secondvector[which.min(matchdist)] )
}
res<-data.frame(firstvector=firstvector,match=match,divergence=mindist, sortedmatches=sortedmatches, stringsAsFactors = F)
res

यह डेटाफ्रेम कॉलम फर्स्टवेक्टर में पहला वेक्टर दिखाता है, कॉलम मैच में दूसरेवेक्टर का सबसे बढ़िया, कॉलम डाइवर्जेंस में इसकी दूरी, और ओपी की तरह कॉलम सॉर्डमैच में सभी महत्वपूर्ण मैचों का आदेश देता है।


2
यद्यपि कार्यान्वयन को अक्सर प्रश्नों में मूल सामग्री के साथ मिलाया जाता है, हमें आँकड़े, मशीन सीखने आदि के बारे में जानकारी प्रदान करने के लिए एक साइट माना जाता है, कोड नहीं। यह कोड प्रदान करने के लिए अच्छा हो सकता है, लेकिन कृपया उन लोगों के लिए पाठ में अपने उत्तर को विस्तृत करें, जो कोड से उत्तर को पहचानने और निकालने के लिए इस भाषा को अच्छी तरह से नहीं पढ़ते हैं।
गंग - मोनिका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.