Data.frame में एक स्तंभ जोड़ना


115

मेरे पास data.frame नीचे है। मैं एक कॉलम जोड़ना चाहता हूं जो कॉलम 1 ( h_no) के अनुसार मेरे डेटा को वर्गीकृत करता है , उस तरह से h_no 1,2,3,4 की पहली श्रृंखला कक्षा 1, h_no(1 से 7) की दूसरी श्रृंखला कक्षा 2 आदि है। जैसे कि अंतिम कॉलम में दिखाया गया है।

h_no  h_freq  h_freqsq
1     0.09091 0.008264628 1
2     0.00000 0.000000000 1
3     0.04545 0.002065702 1
4     0.00000 0.000000000 1  
1     0.13636 0.018594050 2
2     0.00000 0.000000000 2
3     0.00000 0.000000000 2
4     0.04545 0.002065702 2
5     0.31818 0.101238512 2
6     0.00000 0.000000000 2
7     0.50000 0.250000000 2 
1     0.13636 0.018594050 3 
2     0.09091 0.008264628 3
3     0.40909 0.167354628 3
4     0.04545 0.002065702 3

जवाबों:


155

आप विभिन्न तकनीकों का उपयोग करके अपने डेटा में एक कॉलम जोड़ सकते हैं। उद्धरण नीचे, प्रासंगिक सहायता पाठ का "विवरण" अनुभाग से आते हैं [[.data.frame

डेटा फ़्रेम को कई मोड में अनुक्रमित किया जा सकता है। जब [और [[एक एकल वेक्टर इंडेक्स ( x[i]या x[[i]]) के साथ उपयोग किया जाता है , तो वे डेटा फ़्रेम को इंडेक्स करते हैं जैसे कि यह एक सूची थी।

my.dataframe["new.col"] <- a.vector
my.dataframe[["new.col"]] <- a.vector

के लिए data.frame विधि $, xएक सूची के रूप में व्यवहार करती है

my.dataframe$new.col <- a.vector

जब [और [[दो सूचकांकों के साथ उपयोग किया जाता है ( x[i, j]और x[[i, j]]) वे मैट्रिक्स को अनुक्रमित करने की तरह काम करते हैं

my.dataframe[ , "new.col"] <- a.vector

चूंकि यह data.frameमान लिया जाता है कि यदि आप निर्दिष्ट नहीं करते हैं कि आप कॉलम या पंक्तियों के साथ काम कर रहे हैं, तो यह मान लेगा कि आपके पास कॉलम है।


आपके उदाहरण के लिए, यह काम करना चाहिए:

# make some fake data
your.df <- data.frame(no = c(1:4, 1:7, 1:5), h_freq = runif(16), h_freqsq = runif(16))

# find where one appears and 
from <- which(your.df$no == 1)
to <- c((from-1)[-1], nrow(your.df)) # up to which point the sequence runs

# generate a sequence (len) and based on its length, repeat a consecutive number len times
get.seq <- mapply(from, to, 1:length(from), FUN = function(x, y, z) {
            len <- length(seq(from = x[1], to = y[1]))
            return(rep(z, times = len))
         })

# when we unlist, we get a vector
your.df$group <- unlist(get.seq)
# and append it to your original data.frame. since this is
# designating a group, it makes sense to make it a factor
your.df$group <- as.factor(your.df$group)


   no     h_freq   h_freqsq group
1   1 0.40998238 0.06463876     1
2   2 0.98086928 0.33093795     1
3   3 0.28908651 0.74077119     1
4   4 0.10476768 0.56784786     1
5   1 0.75478995 0.60479945     2
6   2 0.26974011 0.95231761     2
7   3 0.53676266 0.74370154     2
8   4 0.99784066 0.37499294     2
9   5 0.89771767 0.83467805     2
10  6 0.05363139 0.32066178     2
11  7 0.71741529 0.84572717     2
12  1 0.10654430 0.32917711     3
13  2 0.41971959 0.87155514     3
14  3 0.32432646 0.65789294     3
15  4 0.77896780 0.27599187     3
16  5 0.06100008 0.55399326     3

कॉलम जोड़ने की अंतिम दो विधियों में क्या अंतर है?
huon

2
@ huon-dbaupp एक अल्पविराम के साथ विधि स्पष्ट है और यह मैट्रिसेस पर भी काम करेगा, जबकि अंतिम डेटा पर केवल काम करता है। यदि कोई अल्पविराम प्रदान नहीं किया जाता है, R मान लेता है कि आपके पास कॉलम है।
रोमन लुसट्रिक 12

12

आसानी से: आपका डेटा फ़्रेम ए है

b <- A[,1]
b <- b==1
b <- cumsum(b)

फिर आपको कॉलम बी मिलता है।


अच्छा और छोटा। मैं सिर्फ अंतिम तत्व को बदलूंगा ताकि cumsum(b) -> bपरिणाम होने के बजाय मूल डेटा फ्रेम में एक कॉलम के रूप में सीधे जोड़ दिया जाए, जैसे कुछ A$groups <- cumsum(b)
A5C1D2H2I1M1N2O1R2T1

cumsum(b)आपको लंबाई 3 का वेक्टर देगा, या मैं कुछ याद कर रहा हूं?
रोमन लुसट्रिक

@ RomanLuštrik, dbaupp का समाधान देखें, जिसमें बताया गया है कि इस मामले में कम्सम कैसे काम करेगा।
a5C1D2H2I1M1N2O1R2T1

2
@ RomanLuštrik, इस समाधान को एक पंक्ति में वास्तव में अच्छी तरह से लिखा जा सकता है। अपने your.dfडेटा का उपयोग करते हुए , आप बस your.df$group = cumsum(your.df[, 1]==1)अपना नया समूह कॉलम प्राप्त कर सकते हैं ।
a5C1D2H2I1M1N2O1R2T1

7

यदि मैं प्रश्न को सही ढंग से समझता हूं, तो आप यह जानना चाहते हैं कि जब h_noवृद्धि नहीं होती है और तब वेतन वृद्धि होती है class। (मैं इस समस्या को हल करने के माध्यम से चलने जा रहा हूं, अंत में एक स्व-निहित फ़ंक्शन है।)

काम कर रहे

हम h_noपल के लिए केवल कॉलम की परवाह करते हैं, इसलिए हम डेटा फ्रेम से इसे निकाल सकते हैं:

> h_no <- data$h_no

हम पता लगाना चाहते हैं कि कब h_noऊपर नहीं जाना है, जो कि हम तब काम कर सकते हैं जब लगातार तत्वों के बीच का अंतर नकारात्मक या शून्य हो। R वह diffफ़ंक्शन प्रदान करता है जो हमें अंतर का सदिश प्रदान करता है :

> d.h_no <- diff(h_no)
> d.h_no
 [1]  1  1  1 -3  1  1  1  1  1  1 -6  1  1  1

एक बार जब हम ऐसा कर लेते हैं, तो यह एक सरल बात है कि जो गैर-सकारात्मक हैं उन्हें ढूंढना है:

> nonpos <- d.h_no <= 0
> nonpos
 [1] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
[13] FALSE FALSE

आर में, TRUEऔर FALSEमूल रूप से के रूप में ही हैं 1और 0इसलिए, अगर हम संचयी राशि प्राप्त करते हैं nonpos, तो यह उचित स्पॉट में 1 (1) की वृद्धि करेगा। cumsumसमारोह (जो मूल रूप से के विपरीत है diff) कर सकते हैं।

> cumsum(nonpos)
 [1] 0 0 0 1 1 1 1 1 1 1 2 2 2 2

लेकिन, दो समस्याएं हैं: संख्या एक बहुत छोटी है; और, हम पहले तत्व को याद कर रहे हैं (प्रथम श्रेणी में चार होने चाहिए)।

पहली समस्या बस हल है 1+cumsum(nonpos):। और दूसरे को केवल 1वेक्टर के सामने जोड़ने की आवश्यकता होती है , क्योंकि पहला तत्व हमेशा कक्षा में होता है 1:

 > classes <- c(1, 1 + cumsum(nonpos))
 > classes
  [1] 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3

अब, हम इसे अपने डेटा फ्रेम पर वापस जोड़ सकते हैं cbind( class=सिंटैक्स का उपयोग करके , हम कॉलम को classशीर्षक दे सकते हैं ):

 > data_w_classes <- cbind(data, class=classes)

और data_w_classesअब परिणाम होता है।

अंतिम परिणाम

हम लाइनों को एक साथ संपीड़ित कर सकते हैं और इसे एक फ़ंक्शन में लपेट सकते हैं ताकि इसका उपयोग करना आसान हो सके:

classify <- function(data) {
   cbind(data, class=c(1, 1 + cumsum(diff(data$h_no) <= 0)))
}

या, चूंकि यह classएक कारक होने के लिए समझ में आता है:

classify <- function(data) {
   cbind(data, class=factor(c(1, 1 + cumsum(diff(data$h_no) <= 0))))
}

आप या तो फ़ंक्शन का उपयोग करते हैं:

> classified <- classify(data) # doesn't overwrite data
> data <- classify(data) # data now has the "class" column

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


2

रोमन के जवाब के अलावा, ऐसा कुछ सरल भी हो सकता है। ध्यान दें कि मैंने इसका परीक्षण नहीं किया है क्योंकि मेरे पास अभी R तक पहुंच नहीं है।

# Note that I use a global variable here
# normally not advisable, but I liked the
# use here to make the code shorter
index <<- 0
new_column = sapply(df$h_no, function(x) {
  if(x == 1) index = index + 1
  return(index)
})

फ़ंक्शन मानों पर पुनरावृति करता है n_hoऔर हमेशा उस मान को लौटाता है जो वर्तमान मूल्य से संबंधित है। यदि मान का 1पता लगाया जाता है, तो हम वैश्विक चर बढ़ाते हैं indexऔर जारी रखते हैं।


मुझे वैश्विक चर के साथ हैक पसंद है। अतः सी.आई.एस. : पी
रोमन लुसट्रिक

2

मेरा मानना ​​है कि "cbind" का उपयोग आर में एक डेटा फ्रेम में कॉलम जोड़ने का सबसे सरल तरीका है। एक उदाहरण के नीचे:

    myDf = data.frame(index=seq(1,10,1), Val=seq(1,10,1))
    newCol= seq(2,20,2)
    myDf = cbind(myDf,newCol)


0

समूहों की संख्या ( xइन mapply) और इसकी लंबाई ( yमें mapply) की पहचान के आधार पर दृष्टिकोण

mytb<-read.table(text="h_no  h_freq  h_freqsq group
1     0.09091 0.008264628 1
2     0.00000 0.000000000 1
3     0.04545 0.002065702 1
4     0.00000 0.000000000 1  
1     0.13636 0.018594050 2
2     0.00000 0.000000000 2
3     0.00000 0.000000000 2
4     0.04545 0.002065702 2
5     0.31818 0.101238512 2
6     0.00000 0.000000000 2
7     0.50000 0.250000000 2 
1     0.13636 0.018594050 3 
2     0.09091 0.008264628 3
3     0.40909 0.167354628 3
4     0.04545 0.002065702 3", header=T, stringsAsFactors=F)
mytb$group<-NULL

positionsof1s<-grep(1,mytb$h_no)

mytb$newgroup<-unlist(mapply(function(x,y) 
  rep(x,y),                      # repeat x number y times
  x= 1:length(positionsof1s),    # x is 1 to number of nth group = g1:g3
  y= c( diff(positionsof1s),     # y is number of repeats of groups g1 to penultimate (g2) = 4, 7
        nrow(mytb)-              # this line and the following gives number of repeat for last group (g3)
          (positionsof1s[length(positionsof1s )]-1 )  # number of rows - position of penultimate group (g2) 
      ) ) )
mytb
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.