2010-11-29 15 views
53

मैं तीन या अधिक स्वतंत्र चर, आर वैक्टर के रूप में प्रतिनिधित्व किया है ताकि तरह:कार्तीय उत्पाद डेटा फ्रेम

A <- c(1,2,3) 
B <- factor(c('x','y')) 
C <- c(0.1,0.5) 

और मैं उन सभी का कार्तीय उत्पाद लेने के लिए और एक डेटा में परिणाम रखना चाहते हैं फ्रेम, इस तरह:

A B C 
1 x 0.1 
1 x 0.5 
1 y 0.1 
1 y 0.5 
2 x 0.1 
2 x 0.5 
2 y 0.1 
2 y 0.5 
3 x 0.1 
3 x 0.5 
3 y 0.1 
3 y 0.5 

मैं मैन्युअल rep के लिए कॉल बाहर लिख कर ऐसा कर सकते हैं:

d <- data.frame(A = rep(A, times=length(B)*length(C)), 
       B = rep(B, times=length(A), each=length(C)), 
       C = rep(C, each=length(A)*length(B)) 

लेकिन ऐसा करने के लिए एक और शानदार तरीका होना चाहिए, हां? productitertools में नौकरी का हिस्सा है, लेकिन मुझे एक इटरेटर के आउटपुट को अवशोषित करने और इसे डेटा फ्रेम में रखने का कोई तरीका नहीं मिल रहा है। कोई सुझाव?

पेज। इस गणना में अगला चरण

d$D <- f(d$A, d$B, d$C) 

इसलिए यदि आप एक साथ दोनों चरणों को करने का कोई तरीका जानते हैं, तो यह भी सहायक होगा।

+0

यह उपयोगी होगा यदि आप निर्दिष्ट करते हैं कि फ़ंक्शन एफ क्या करता है। – Ramnath

+0

'f' कई अलग-अलग बालों वाली गणितीय गणनाओं में से एक के लिए प्लेसहोल्डर है, लेकिन इस प्रश्न के प्रयोजनों के लिए, मुझे लगता है कि * आपको लगता है कि जिस चीज़ को आप जानना चाहते हैं वह यह है कि वे सभी उचित प्रकार के एन वैक्टर लेते हैं और एक वेक्टर का उत्पादन करते हैं; सभी इनपुट एक ही लंबाई होना चाहिए, और आउटपुट भी लंबाई है। – zwol

+0

मैं इस प्रश्न के शीर्षक को बदलने की सिफारिश करता हूं ... "डेटा टेबल" का अर्थ अब आर –

उत्तर

57

आप

संपादित करें का उपयोग कर सकते हैं: do.call का उपयोग कर दूसरे भाग को प्राप्त करने के लिए एक विकल्प, समारोह mdply है। यहाँ कोड

d = expand.grid(x = A, y = B, z = C) 
d = mdply(d, f) 

इसके उपयोग एक छोटी सी समारोह 'पेस्ट' का उपयोग वर्णन करने के लिए है, तो आप कोशिश कर सकते हैं

d = mdply(d, 'paste', sep = '+'); 
+0

आह! मुझे पता था कि एक मानक लाइब्रेरी दिनचर्या होनी चाहिए जिसने ऐसा किया, लेकिन उसे क्या नहीं कहा जा सका। अगर किसी के पास भाग दो का जवाब है, तो मैं सवाल खोलने जा रहा हूं। – zwol

+0

यदि एफ एक कस्टम फ़ंक्शन है, तो आप इसे डेटा फ्रेम को एक तर्क के रूप में स्वीकार करने के लिए संशोधित कर सकते हैं और फ़ंक्शन को घटक वैक्टर में विभाजित करने दें – Ramnath

+0

प्लीयर दस्तावेज़ों पर घूर रहा था, लेकिन यह नहीं पकड़ा कि यह 'mdply के लिए था। धन्यवाद। – zwol

0

मुझे याद है कभी नहीं हो सकता है कि मानक समारोह expand.grid। तो यहाँ एक और संस्करण है।

crossproduct <- function(...,FUN='data.frame') { 
    args <- list(...) 
    n1 <- names(args) 
    n2 <- sapply(match.call()[1+1:length(args)], as.character) 
    nn <- if (is.null(n1)) n2 else ifelse(n1!='',n1,n2) 
    dims <- sapply(args,length) 
    dimtot <- prod(dims) 
    reps <- rev(cumprod(c(1,rev(dims))))[-1] 
    cols <- lapply(1:length(dims), function(j) 
       args[[j]][1+((1:dimtot-1) %/% reps[j]) %% dims[j]]) 
    names(cols) <- nn 
    do.call(match.fun(FUN),cols) 
} 

A <- c(1,2,3) 
B <- factor(c('x','y')) 
C <- c(.1,.5) 

crossproduct(A,B,C) 

crossproduct(A,B,C, FUN=function(...) paste(...,sep='_')) 
5

यहाँ दोनों करने के लिए एक रास्ता है, expand.grid के रामनाथ के सुझाव का उपयोग कर:

f <- function(x,y,z) paste(x,y,z,sep="+") 
d <- expand.grid(x=A, y=B, z=C) 
d$D <- do.call(f, d) 

ध्यान दें कि d पर do.call काम करता है "के रूप में-है" क्योंकि एक data.frame एक list है। लेकिन do.callf के तर्क नामों से मेल खाने के लिए d के कॉलम नामों की अपेक्षा करता है।

+0

'd' केवल 'expand.grid' कॉल द्वारा परिभाषित किया गया है ... – zwol

+0

@Zack: धन्यवाद; मैंने अपनी प्रतिक्रिया अपडेट की है। यह एक लाइनर नहीं है, लेकिन 'एफ' का मूल्यांकन करना प्रत्येक तर्क में टाइप करने से 'do.call' के साथ अभी भी आसान है। –

+0

अच्छी पुरानी do.call चाल। अच्छा है! – Ramnath

13

डेटाफ्रेम में हेरफेर करने वाला एक फ़ंक्शन है, जो इस मामले में सहायक है।

यह विभिन्न शामिल हो सकता है (एसक्यूएल टर्मिनोलॉजी में), जबकि कार्टेशियन उत्पाद एक विशेष मामला है।

आपको वैरिबल्स को डेटा फ्रेम में पहले कनवर्ट करना होगा, क्योंकि यह पैरामीटर के रूप में डेटा फ्रेम लेता है।

तो कुछ इस तरह करना होगा:

A.B=merge(data.frame(A=A), data.frame(B=B),by=NULL); 
A.B.C=merge(A.B, data.frame(C=C),by=NULL); 

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

merge(x, y, by = intersect(names(x), names(y)), by.x = by, by.y = by, all = FALSE, all.x = all, all.y = all, sort = TRUE, suffixes = c(".x",".y"), incomparables = NULL, ...)

"द्वारा या दोनों by.x और से है।http://stat.ethz.ch/R-manual/R-patched/library/base/html/merge.html

3

अद्भुत data.table उपयोग पर विचार करें: y लंबाई 0 (लंबाई शून्य वेक्टर या शून्य), परिणाम, आर के हैं, x और y "

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

library(data.table) 
d <- CJ(x=A, y=B, z=C) # Cross join 
d[, w:=f(x,y,z)] # Mutates the data.table 

या एक पंक्ति में

d <- CJ(x=A, y=B, z=C)[, w:=f(x,y,z)]