इस से एक डेटा.फ्रेम को फिर से आकार देने की जरूरत है

  TestID Machine1Measure Machine1Count Machine2Measure Machine2Count
1  10006              11            14              16            24
2  10007              23            27              32            35

इसके लिए:

  TestID Machine Measure Count
1  10006       1      11    14
2  10006       2      16    24
3  10007       1      23    27
4  10007       2      32    35

प्रत्येक बनाने के लिए नीचे कोड है। आर में फिर से आकार देना देखा, लेकिन यह पता नहीं लगा सका कि नामों को कैसे विभाजित किया जाए

नोट: यह कॉलम का सबसेट है - 70-140 मशीनें हैं। मैं इसे सरल कैसे बना सकता हूं?

b <-data.frame(10006:10007, matrix(c(11,23,14,27,16,32,24,35),2,4)) 
colnames(b) <- c("TestID", "Machine1Measure", "Machine1Count", "Machine2Measure", "Machine2Count") 

a<-data.frame(matrix(c(10006,10006,10007,10007,1,2,1,2,11,16,23,32,14,24,27,35),4,4)) 
colnames(a) <- c("TestID", "Machine", "Measure", "Count") 

b
a
0
eAndy 27 सितंबर 2018, 08:41

3 जवाब

सबसे बढ़िया उत्तर

data.table यह सब एक melt के भीतर कर सकता है, जो मॉरीट्सएवर्स द्वारा प्रदान किए गए (पूरी तरह से काम करने वाले) साफ-सुथरे समाधान से लगभग 30 गुना तेज है।

यह patterns का उपयोग उनके नामों में 'माप' और 'गणना' वाले कॉलम को परिभाषित करने के लिए करता है, और फिर इन कॉलमों को value.name में कॉलम नामों में पिघला देता है।

library( data.table )
melt( setDT( b), 
      id.vars = c("TestID"), 
      measure.vars = patterns( ".*Measure", ".*Count"), 
      variable.name = "Machine", 
      value.name = c("Measure", "Count") )

#    TestID Machine Measure Count
# 1:  10006       1      11    14
# 2:  10007       1      23    27
# 3:  10006       2      16    24
# 4:  10007       2      32    35

बेंच मार्किंग

# Unit: microseconds
#       expr      min        lq      mean    median        uq        max neval
# data.table  182.265  200.3405  245.0403  234.0825  264.6605   3137.967  1000
# reshape    1757.575 1840.7240 2180.4957 1938.3335 2011.3895 100429.392  1000
# tidyverse  6173.203 6430.7830 6925.6034 6569.9670 6763.9810  29722.714  1000
3
Wimpel 27 सितंबर 2018, 09:39

निम्नलिखित आपके अपेक्षित आउटपुट को पुन: उत्पन्न करता है:

df %>%
    gather(key, value, -TestID) %>%
    separate(key, into = c("tmp", "what"), sep = "(?<=\\d)") %>%
    separate(tmp, into = c("tmp", "Machine"), sep = "(?=\\d+)") %>%
    spread(what, value) %>%
    select(-tmp)
#  TestID Machine Count Measure
#1  10006       1    14      11
#2  10006       2    24      16
#3  10007       1    27      23
#4  10007       2    35      32

व्याख्या: हम डेटा को वाइड से लॉन्ग में फिर से आकार देते हैं, और दो separate कॉल का उपयोग करते हैं, ताकि लॉन्ग से वाइड में फिर से आकार देने से पहले विभिन्न मानों और आईडी को अलग किया जा सके। (हम आवश्यक फ़ील्ड में कुंजियों को अलग करने के लिए सकारात्मक लुक-फ़ॉरवर्ड और पॉज़िटिव लुक-बैक का उपयोग करते हैं।)


नमूना डेटा

df <- read.table(text =
    "  TestID Machine1Measure Machine1Count Machine2Measure Machine2Count
1  10006              11            14              16            24
2  10007              23            27              32            35", header = T)
5
Maurits Evers 27 सितंबर 2018, 08:56

और चूंकि अब कोई और पसंद नहीं करता reshape(), मैं एक उत्तर जोड़ूंगा:

reshape(
  setNames(b, sub("^.+(\\d+)(.+)$", "\\2.\\1", names(b))),
  idvar="TestID", direction="long", varying=-1, timevar="Machine"
)

#        TestID Machine Measure Count
#10006.1  10006       1      11    14
#10007.1  10007       1      23    27
#10006.2  10006       2      16    24
#10007.2  10007       2      32    35

यह शुद्ध गति के लिए कभी भी data.table के साथ प्रतिस्पर्धा नहीं करेगा, लेकिन 2M पंक्तियों पर संक्षिप्त परीक्षण का उपयोग करके:

bbig <- b[rep(1:2,each=1e6),]
bbig$TestID <- make.unique(as.character(bbig$TestID))

#data.table -  0.06 secs
#reshape    -  2.30 secs
#tidyverse  - 56.60 secs
3
thelatemail 27 सितंबर 2018, 09:41