2010-05-24 22 views
76
df <- data.frame(var1=c('a', 'b', 'c'), var2=c('d', 'e', 'f'), freq=1:3) 

क्या ऊपर data.frame के पहले दो स्तंभों का विस्तार करने के लिए सबसे आसान तरीका है अनुकरण की संख्या निर्दिष्ट, ताकि प्रत्येक पंक्ति समय की संख्या प्रकट होता है कॉलम 'freq' में निर्दिष्ट?data.frame की प्रत्येक पंक्ति को दोहराने और प्रत्येक पंक्ति

दूसरे शब्दों में, इस से जाना:

df 
    var1 var2 freq 
1 a d 1 
2 b e 2 
3 c f 3 
इस के लिए

:

df.expanded 
    var1 var2 
1 a d 
2 b e 
3 b e 
4 c f 
5 c f 
6 c f 

उत्तर

106

यहाँ एक समाधान:

df.expanded <- df[rep(row.names(df), df$freq), 1:2] 

परिणाम:

var1 var2 
1  a d 
2  b e 
2.1 b e 
3  c f 
3.1 c f 
3.2 c f 
+0

वाह! मैं हमेशा भूल जाता हूं कि आप इस तरह स्क्वायर ब्रैकेट का उपयोग कर सकते हैं। मैं केवल सबसेटिंग या रीडरिंग के लिए अनुक्रमण के बारे में सोचता रहता हूं। मेरे पास एक और समाधान था जो बहुत कम सुरुचिपूर्ण है और इसमें कोई संदेह नहीं है। मैं वैसे भी पोस्ट कर सकता हूं ताकि अन्य तुलना कर सकें। – wkmor1

+14

बड़े 'data.frame' के लिए' seq.int (1, nrow (df)) 'या 'seq_len (nrow (df))' '। Line.names (df)' को प्रतिस्थापित करने के लिए अधिक कुशल है। – Marek

+0

यह एक बड़े डेटा फ्रेम के लिए fantastically काम किया - 1.5 मिलियन पंक्तियों, 5 cols, बहुत जल्दी चला गया। धन्यवाद! – gabe

13

@ neilfws का समाधान data.frame एस के लिए बहुत अच्छा काम करता है, लेकिन data.table के लिए नहीं है क्योंकि उनमें row.names संपत्ति की कमी है। यह दृष्टिकोण दोनों के लिए काम करता है:

df.expanded <- df[rep(seq(nrow(df)), df$freq), 1:2] 

data.table के लिए ही आप और with=F जोड़ने की आवश्यकता होगी वैकल्पिक रूप से निकाल सकते हैं df$:

dt <- data.table(df) 
dt.expanded <- dt[rep(seq(.N), freq), !"freq", with=F] 
+6

'.N' अब' dt [] 'के पहले तर्क में पहुंच योग्य है, इसलिए आप' dt [rep (seq (.N), freq), "freq", = fALSE] या इसी तरह के कर सकते हैं। – Frank

+0

धन्यवाद, अद्यतन किया गया। –

+1

एक और विकल्प: 'डीएफ [प्रतिनिधि (सीईसी (एन), freq)] [, freq: = NULL] ' – Jaap

33

उपयोग expandRows()splitstackshape पैकेज से:

library(splitstackshape) 
expandRows(df, "freq") 

सरल वाक्यविन्यास, बहुत तेज़, data.frame या data.table पर काम करता है।

परिणाम:

var1 var2 
1  a d 
2  b e 
2.1 b e 
3  c f 
3.1 c f 
3.2 c f 
2

मामले में आप, बहुत तेजी से चलाना चाहिए जो बहुत बड़े data.frames मैं इसे एक data.table में परिवर्तित करने की सलाह देते हैं और निम्नलिखित का प्रयोग करेंगे पर यह कार्रवाई क्या करना है:

library(data.table) 
dt <- data.table(df) 
dt.expanded <- dt[ ,list(freq=rep(1,freq)),by=c("var1","var2")] 
dt.expanded[ ,freq := NULL] 
dt.expanded 

देखें कि बहुत तेजी से इस समाधान है:

df <- data.frame(var1=1:2e3, var2=1:2e3, freq=1:2e3) 
system.time(df.exp <- df[rep(row.names(df), df$freq), 1:2]) 
## user system elapsed 
## 4.57 0.00 4.56 
dt <- data.table(df) 
system.time(dt.expanded <- dt[ ,list(freq=rep(1,freq)),by=c("var1","var2")]) 
## user system elapsed 
## 0.05 0.01 0.06 
+0

मुझे एक त्रुटि मिलती है:' प्रतिनिधि में त्रुटि (1, freq): अवैध 'समय' तर्क'। और दिया कि पहले से ही एक डेटा है।तालिका इस प्रश्न का उत्तर देती है, आप वर्णन करना चाहेंगे कि आपका दृष्टिकोण अलग कैसे है या जब यह वर्तमान डेटा.table उत्तर से बेहतर है। या यदि कोई बड़ा अंतर नहीं है, तो आप इसके बजाय मौजूदा उत्तर पर टिप्पणी के रूप में जोड़ सकते हैं। –

+0

@ सैमफिरके: आपकी टिप्पणी के लिए धन्यवाद। अजीब, मैंने बस इसे फिर से कोशिश की और मुझे ऐसी कोई त्रुटि नहीं मिली। क्या आप ओपी के सवाल से मूल 'डीएफ' का उपयोग करते हैं? मेरा जवाब बेहतर है क्योंकि दूसरा जवाब 'data.tframe' सिंटैक्स का उपयोग करके 'data.table' पैकेज का दुरुपयोग करने का प्रकार है,' data.table' के सामान्य प्रश्न देखें: "कॉलम को संख्या के अनुसार संदर्भित करना आम तौर पर खराब अभ्यास है नाम के बजाए। " – vonjd

+1

स्पष्टीकरण के लिए धन्यवाद। आपका कोड ओपी द्वारा पोस्ट किए गए नमूना 'df' पर मेरे लिए काम करता है, लेकिन जब मैंने इसे बड़े डेटा पर बेंचमार्क करने का प्रयास किया। फ्रेम मुझे यह त्रुटि मिली। मैं जिस डेटा.फ्रेम का उपयोग करता था वह था: 'set.seed (1) dfbig <- data.frame (var1 = नमूना (अक्षर, 1000, प्रतिस्थापित = TRUE), var2 = नमूना (LETTERS, 1000, प्रतिस्थापित = TRUE), freq = नमूना (1:10, 1000, प्रतिस्थापित = TRUE)) 'छोटे डेटा.फ्रेम पर, मूल उत्तर मेरे बेंचमार्किंग में अच्छा करता है, यह केवल बड़े डेटा के लिए अच्छी तरह से स्केल नहीं करता है। फ्रेम। अन्य तीन उत्तरों इस बड़े डेटा के साथ सफलतापूर्वक भाग गए। फ्रेम। –

4

वर्ष सवाल, tidyverse में नए क्रिया:

library(tidyr) # version >= 0.8.0 
df <- data.frame(var1=c('a', 'b', 'c'), var2=c('d', 'e', 'f'), freq=1:3) 
df %>% 
    uncount(freq) 

संबंधित मुद्दे