लंबे समय से विस्तृत प्रारूप में डेटा को कैसे फिर से व्यवस्थित करें


262

मुझे निम्नलिखित डेटा फ़्रेम को पुन: व्यवस्थित करने में समस्या हो रही है:

set.seed(45)
dat1 <- data.frame(
    name = rep(c("firstName", "secondName"), each=4),
    numbers = rep(1:4, 2),
    value = rnorm(8)
    )

dat1
       name  numbers      value
1  firstName       1  0.3407997
2  firstName       2 -0.7033403
3  firstName       3 -0.3795377
4  firstName       4 -0.7460474
5 secondName       1 -0.8981073
6 secondName       2 -0.3347941
7 secondName       3 -0.5013782
8 secondName       4 -0.1745357

मैं इसे फिर से खोलना चाहता हूं ताकि प्रत्येक अद्वितीय "नाम" चर एक पंक्तिनाम हो, जिसमें "मान" उस पंक्ति के साथ टिप्पणियों के रूप में और "संख्याएं" कॉलनेम के रूप में हों। इस तरह की तरह:

     name          1          2          3         4
1  firstName  0.3407997 -0.7033403 -0.3795377 -0.7460474
5 secondName -0.8981073 -0.3347941 -0.5013782 -0.1745357

मैं देखा है meltऔर castऔर कुछ अन्य बातें, लेकिन कोई भी काम करने के लिए लग रहे हैं।



4
@ फ्रेंक: यह काफी बेहतर शीर्षक है। दीर्घ-रूप और विस्तृत-रूप मानक शब्द हैं। उन शर्तों पर खोज करने से अन्य उत्तर नहीं मिल सकता है।
स्मिकी

एक और सवाल: इसे वापस कैसे बदला जाए?
हैप्पीलांग

जवाबों:


255

reshapeसमारोह का उपयोग :

reshape(dat1, idvar = "name", timevar = "numbers", direction = "wide")

13
+1 और आपको बाहरी पैकेजों पर निर्भर होने की आवश्यकता नहीं है, क्योंकि यह reshapeआता है stats। यह उल्लेख नहीं है कि यह तेज है! =)
aL3xa

@indra_patil - मैं संभवतः reshape2 पैकेज का उपयोग करूँगा जैसा कि अन्य उत्तरों में से एक में दर्शाया गया है। आप एक नया प्रश्न बना सकते हैं जो आपके उपयोग के मामले के लिए विशिष्ट है और यदि आप इसे समझ नहीं सकते हैं तो इसे पोस्ट करें।
चेस

5
reshapeएक भयानक समारोह एपीआई के लिए एक उत्कृष्ट उदाहरण है। यह बेकार के बहुत करीब है।
NoBackingDown

14
reshapeटिप्पणियाँ और इसी तरह के तर्क के नाम कि सभी उपयोगी नहीं हैं। हालाँकि, मैंने पाया है कि लंबे समय तक विस्तृत होने के लिए, आपको data =अपना डेटा प्रदान करने की आवश्यकता है। फ़्रेम, idvar= वह चर जो आपके समूहों की पहचान करता है, v.names= वे चर जो कि विस्तृत प्रारूप में कई कॉलम बन जाएंगे, timevar= वैरिएबल जिसमें वे मान होंगे जो जोड़ दिए जाएंगे। करने के लिए v.namesविस्तृत प्रारूप में, direction = wide, और sep = "_"। पर्याप्त रूप से स्पष्ट? ;)
ब्रायन डी

3
मैं कहूंगा कि आधार R अभी भी 2 से 1 के कारक द्वारा वोट-वार जीतता है
vonjd

129

नई (2014 में) tidyrपैकेज भी बस इस करता है, के साथ gather()/ spread()के लिए संदर्भ जा रहा है melt/ cast

संपादित करें: अब, 2019 में, tidyr v 1.0 को लॉन्च किया गया है और सेट spreadऔर gatherडेप्रिसिएशन पथ पर, इसके बजाय प्राथमिकता pivot_widerऔर pivot_longer, जिसे आप इस उत्तर में वर्णित पा सकते हैं । यदि आप संक्षिप्त जीवन में एक संक्षिप्त झलक चाहते हैं तो पढ़ें spread/gather

library(tidyr)
spread(dat1, key = numbers, value = value)

से GitHub ,

tidyrकी एक reframing है reshape2सुथरा डेटा ढांचा साथ देने के लिए तैयार किया गया है, और काम हाथ में हाथ के साथ करने के लिए magrittrऔर dplyrडेटा विश्लेषण के लिए एक ठोस पाइपलाइन का निर्माण करने के लिए।

जैसे reshape2रिशेप से कम किया, tidyrउससे कम करता है reshape2। यह विशेष रूप से डेटा को टिड्डिंग के लिए डिज़ाइन किया गया है, न कि सामान्य रीशैपिंग जो reshape2करता है, या जो सामान्य एकत्रीकरण करता है वह फिर से करता है। विशेष रूप से, अंतर्निहित तरीके केवल डेटा फ़्रेम के लिए काम करते हैं, और tidyrकोई मार्जिन या एकत्रीकरण प्रदान नहीं करते हैं।


5
बस के लिए एक लिंक जोड़ना चाहते थे आर कुकबुक पेज से इन कार्यों के उपयोग की चर्चा tidyrऔर reshape2। यह अच्छे उदाहरण और स्पष्टीकरण प्रदान करता है।
जेक

71

आप इसे reshape()फ़ंक्शन के साथ , या reshape पैकेज में melt()/ cast()फ़ंक्शन के साथ कर सकते हैं । दूसरे विकल्प के लिए, उदाहरण कोड है

library(reshape)
cast(dat1, name ~ numbers)

या उपयोग कर रहे हैं reshape2

library(reshape2)
dcast(dat1, name ~ numbers)

2
यह ध्यान देने योग्य हो सकता है कि यदि आपके पास स्पष्ट "मान" कॉलम नहीं है, तो बस उपयोग करना castया dcastअच्छी तरह से काम नहीं करेगा। कोशिश करो dat <- data.frame(id=c(1,1,2,2),blah=c(8,4,7,6),index=c(1,2,1,2)); dcast(dat, id ~ index); cast(dat, id ~ index)और आपको वह नहीं मिलेगा जो आप उम्मीद करते हैं। आपको स्पष्ट रूप से value/value.var- cast(dat, id ~ index, value="blah")और dcast(dat, id ~ index, value.var="blah")उदाहरण के लिए नोट करने की आवश्यकता है ।
Thelatemail

44

एक अन्य विकल्प अगर प्रदर्शन एक चिंता का विषय है, तो मेल्ट और डकैस फ़ंक्शन के data.tableविस्तार का उपयोग reshape2करना है

( संदर्भ: data.tables का उपयोग करके कुशल पुन: आकार देना )

library(data.table)

setDT(dat1)
dcast(dat1, name ~ numbers, value.var = "value")

#          name          1          2         3         4
# 1:  firstName  0.1836433 -0.8356286 1.5952808 0.3295078
# 2: secondName -0.8204684  0.4874291 0.7383247 0.5757814

और, data.table v1.9.6 के रूप में हम कई कॉलम पर कास्ट कर सकते हैं

## add an extra column
dat1[, value2 := value * 2]

## cast multiple value columns
dcast(dat1, name ~ numbers, value.var = c("value", "value2"))

#          name    value_1    value_2   value_3   value_4   value2_1   value2_2 value2_3  value2_4
# 1:  firstName  0.1836433 -0.8356286 1.5952808 0.3295078  0.3672866 -1.6712572 3.190562 0.6590155
# 2: secondName -0.8204684  0.4874291 0.7383247 0.5757814 -1.6409368  0.9748581 1.476649 1.1515627

5
data.tableदृष्टिकोण सबसे अच्छा है! बहुत कुशल ... आप अंतर देखेंगे जब name30-40 कॉलम का संयोजन होगा !!
joel.wilson 12

क्या होगा यदि मैं अधिकतम लेना चाहता हूं?
टी। फंग

@ T.Fung मुझे समझ नहीं आ रहा है कि आप क्या पूछ रहे हैं। एक नया प्रश्न खोलने के लिए सबसे अच्छा हो सकता है?
सिंबलिक्सएयू

@ Op के प्रश्न 'नाम' और 'संख्या' में @SymbolixAU अद्वितीय संयोजन हैं। क्या होगा अगर वे नहीं थे और मैं धुरी के बाद प्रत्येक संयोजन के लिए अधिकतम मूल्य प्राप्त करना चाहता था? एक समस्या नहीं है अगर बहुत ही मुश्किल से एक सवाल है। सिर्फ विचारों के लिए भोजन। धन्यवाद।
T.Fung

बहुत बढ़िया जवाब। धन्यवाद। एकाधिक स्तंभों के लिए, मैं "त्रुटि .subset2 में (एक्स, मैं, सटीक = सटीक)" हो गया, और data.table dcast के उपयोग के लिए मजबूर कर रहा करके इसे ठीक कर सकता है: देखने stackoverflow.com/a/44271092/190791
Timothée हेनरी

26

आपके उदाहरण डेटाफ्रेम का उपयोग करते हुए, हम कर सकते हैं:

xtabs(value ~ name + numbers, data = dat1)

2
यह एक अच्छा है, लेकिन परिणाम स्वरूप तालिका का है, जो डेटा के रूप में संभालना इतना आसान नहीं हो सकता है। डेटा या data.table, दोनों में बहुत सारे पैकेज हैं
बादलों की संख्या

18

अन्य दो विकल्प:

आधार पैकेज:

df <- unstack(dat1, form = value ~ numbers)
rownames(df) <- unique(dat1$name)
df

sqldf पैकेज:

library(sqldf)
sqldf('SELECT name,
      MAX(CASE WHEN numbers = 1 THEN value ELSE NULL END) x1, 
      MAX(CASE WHEN numbers = 2 THEN value ELSE NULL END) x2,
      MAX(CASE WHEN numbers = 3 THEN value ELSE NULL END) x3,
      MAX(CASE WHEN numbers = 4 THEN value ELSE NULL END) x4
      FROM dat1
      GROUP BY name')

1
हार्डकोडिंग नंबरों के बजाय, क्वेरी को इस तरह सेट किया जा सकता है:ValCol <- unique(dat1$numbers);s <- sprintf("MAX(CASE WHEN numbers = %s THEN value ELSE NULL END) `%s`,", ValCol, ValCol);mquerym <- gsub('.{1}$','',paste(s, collapse = "\n"));mquery <- paste("SELECT name,", mquerym, "FROM dat1", "GROUP BY name", sep = "\n");sqldf(mquery)
M--

13

आधार आर aggregateफ़ंक्शन का उपयोग करना :

aggregate(value ~ name, dat1, I)

# name           value.1  value.2  value.3  value.4
#1 firstName      0.4145  -0.4747   0.0659   -0.5024
#2 secondName    -0.8259   0.1669  -0.8962    0.1681

11

के devel संस्करण के साथ tidyr ‘0.8.3.9000’, वहाँ है pivot_widerऔरpivot_longer एकाधिक स्तंभों के लिए (> लंबे क्रमश: - -> विस्तृत, व्यापक लंबे) 1 से पुन: आकार देने करने के लिए सामान्यीकृत किया जाता है। ओपी के डेटा का उपयोग करना

asingle column long -> चौड़ा

library(dplyr)
library(tidyr)
dat1 %>% 
    pivot_wider(names_from = numbers, values_from = value)
# A tibble: 2 x 5
#  name          `1`    `2`    `3`    `4`
#  <fct>       <dbl>  <dbl>  <dbl>  <dbl>
#1 firstName   0.341 -0.703 -0.380 -0.746
#2 secondName -0.898 -0.335 -0.501 -0.175

-> कार्यक्षमता दिखाने के लिए एक और कॉलम बनाया

dat1 %>% 
    mutate(value2 = value * 2) %>% 
    pivot_wider(names_from = numbers, values_from = c("value", "value2"))
# A tibble: 2 x 9
#  name       value_1 value_2 value_3 value_4 value2_1 value2_2 value2_3 value2_4
#  <fct>        <dbl>   <dbl>   <dbl>   <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
#1 firstName    0.341  -0.703  -0.380  -0.746    0.682   -1.41    -0.759   -1.49 
#2 secondName  -0.898  -0.335  -0.501  -0.175   -1.80    -0.670   -1.00    -0.349

8

आधार reshapeफ़ंक्शन पूरी तरह से ठीक काम करता है:

df <- data.frame(
  year   = c(rep(2000, 12), rep(2001, 12)),
  month  = rep(1:12, 2),
  values = rnorm(24)
)
df_wide <- reshape(df, idvar="year", timevar="month", v.names="values", direction="wide", sep="_")
df_wide

कहाँ पे

  • idvar वर्गों का स्तंभ है जो पंक्तियों को अलग करता है
  • timevar विस्तृत कास्ट करने के लिए कक्षाओं का कॉलम है
  • v.names संख्यात्मक मान वाले स्तंभ है
  • direction विस्तृत या लंबा प्रारूप निर्दिष्ट करता है
  • वैकल्पिक sepतर्क timevarवर्ग नामों के बीच और v.namesआउटपुट में उपयोग किया जाने वाला विभाजक है data.frame

यदि नही idvar मौजूद है, तो reshape()फ़ंक्शन का उपयोग करने से पहले एक बनाएं :

df$id   <- c(rep("year1", 12), rep("year2", 12))
df_wide <- reshape(df, idvar="id", timevar="month", v.names="values", direction="wide", sep="_")
df_wide

बस याद है कि idvarआवश्यक है! timevarऔर v.namesभाग आसान है। इस फ़ंक्शन का आउटपुट दूसरों की तुलना में अधिक अनुमानित है, क्योंकि सब कुछ स्पष्ट रूप से परिभाषित है।


7

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

पूरी प्रणाली दो प्राथमिकताओं या ऑपरेटरों cdata :: MoveValuesToRowsD () और cdata :: MoveValuesToColumnsD () पर आधारित है। इन ऑपरेटरों में पिवट, अन-पिवट, वन-हॉट एन्कोड, ट्रांसपोज़, मूविंग मल्टीपल रो और कॉलम हैं, और कई अन्य सरल विशेष मामलों के रूप में रूपांतरित होते हैं।

सीडीटा प्राइमेटिक्स के संदर्भ में कई अलग-अलग ऑपरेशन लिखना आसान है। ये ऑपरेटर मेमोरी में या बड़े डेटा स्केल पर (डेटाबेस और अपाचे स्पार्क के साथ) बड़े डेटा के लिए cdata :: MoveValuesToRowsN () और cdata :: MoveValuesToColumnnN () वेरिएंट) का उपयोग करते हैं। परिवर्तनों को एक नियंत्रण तालिका द्वारा नियंत्रित किया जाता है जो स्वयं परिवर्तन का एक चित्र (या चित्र) है।

हम पहले कंट्रोल टेबल बनाएंगे ( विवरण के लिए ब्लॉग पोस्ट देखें) और फिर पंक्तियों से स्तंभों तक डेटा की चाल का प्रदर्शन करेंगे।

library(cdata)
# first build the control table
pivotControlTable <- buildPivotControlTableD(table = dat1, # reference to dataset
                        columnToTakeKeysFrom = 'numbers', # this will become column headers
                        columnToTakeValuesFrom = 'value', # this contains data
                        sep="_")                          # optional for making column names

# perform the move of data to columns
dat_wide <- moveValuesToColumnsD(tallTable =  dat1, # reference to dataset
                    keyColumns = c('name'),         # this(these) column(s) should stay untouched 
                    controlTable = pivotControlTable# control table above
                    ) 
dat_wide

#>         name  numbers_1  numbers_2  numbers_3  numbers_4
#> 1  firstName  0.3407997 -0.7033403 -0.3795377 -0.7460474
#> 2 secondName -0.8981073 -0.3347941 -0.5013782 -0.1745357

1

बहुत आसान तरीका है!

devtools::install_github("yikeshu0611/onetree") #install onetree package

library(onetree)
widedata=reshape_toWide(data = dat1,id = "name",j = "numbers",value.var.prefix = "value")
widedata

        name     value1     value2     value3     value4
   firstName  0.3407997 -0.7033403 -0.3795377 -0.7460474
  secondName -0.8981073 -0.3347941 -0.5013782 -0.1745357

यदि आप व्यापक से लंबे समय तक वापस जाना चाहते हैं, तो केवल वाइड से लॉन्ग में बदलें, और वस्तुओं में कोई परिवर्तन नहीं।

reshape_toLong(data = widedata,id = "name",j = "numbers",value.var.prefix = "value")

        name numbers      value
   firstName       1  0.3407997
  secondName       1 -0.8981073
   firstName       2 -0.7033403
  secondName       2 -0.3347941
   firstName       3 -0.3795377
  secondName       3 -0.5013782
   firstName       4 -0.7460474
  secondName       4 -0.1745357
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.