wake-up-neo.com

Hinzufügen einer Spalte zu einem data.frame

Ich habe den Datenrahmen unten. Ich möchte eine Spalte hinzufügen, die meine Daten gemäß Spalte 1 (h_no) so klassifiziert, dass die erste Reihe von h_no 1,2,3,4 Klasse 1 ist, die zweite Reihe von h_no (1 bis 7) Klasse 2 usw. wie in der letzten Spalte angegeben.

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
102

Sie können Ihren Daten mithilfe verschiedener Techniken eine Spalte hinzufügen. Die folgenden Anführungszeichen stammen aus dem Abschnitt "Details" des entsprechenden Hilfetextes [[.data.frame.

Datenrahmen können in mehreren Modi indiziert werden. Wenn [ und [[ mit einem einzelnen Vektorindex (x[i] oder x[[i]]) verwendet werden, indizieren sie den Datenrahmen so, als ob es eine Liste wäre.

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

Die data.frame-Methode für $ behandelt x als Liste

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

Wenn [ und [[ mit zwei Indizes (x[i, j] und x[[i, j]]) verwendet werden, wirken sie wie das Indizieren einer Matrix

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

Da die Methode für data.frame voraussetzt, dass, wenn Sie nicht angeben, ob Sie mit Spalten oder Zeilen arbeiten, davon ausgegangen wird, dass Sie Spalten meinen.


Für Ihr Beispiel sollte dies funktionieren:

# 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
143
Roman Luštrik

Leicht: Ihr Datenrahmen ist A

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

Dann erhalten Sie die Spalte b. 

10
user1333396

Wenn ich die Frage richtig verstanden habe, möchten Sie feststellen, dass der h_no nicht zunimmt und dann die class inkrementiert. (Ich werde durchgehen, wie ich dieses Problem gelöst habe, am Ende gibt es eine eigenständige Funktion.)

Arbeiten

Im Moment kümmern wir uns nur um die Spalte h_no, sodass wir dies aus dem Datenrahmen extrahieren können:

> h_no <- data$h_no

Wir möchten herausfinden, wann h_no nicht nach oben geht, was wir tun können, indem wir herausfinden, wann der Unterschied zwischen aufeinanderfolgenden Elementen entweder negativ oder Null ist. R liefert die diff - Funktion, die uns den Vektor der Unterschiede gibt:

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

Sobald wir das haben, ist es eine einfache Sache, diejenigen zu finden, die nicht positiv sind:

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

In R sind TRUE und FALSE im Wesentlichen dasselbe wie 1 und 0. Wenn wir also die kumulative Summe von nonpos erhalten, steigt sie in (fast) den entsprechenden Stellen um 1. Die Funktion cumsum (die grundsätzlich das Gegenteil von diff ist) kann dies tun.

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

Es gibt jedoch zwei Probleme: Die Zahlen sind zu klein; und das erste Element fehlt (es sollten vier in der ersten Klasse sein).

Das erste Problem ist einfach gelöst: 1+cumsum(nonpos). Und das zweite erfordert nur das Hinzufügen eines 1 vor dem Vektor, da das erste Element immer in der Klasse 1 ist:

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

Jetzt können wir es mit cbind wieder an unseren Datenrahmen anhängen (mithilfe der class=-Syntax können wir der Spalte die class-Überschrift geben):

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

Und data_w_classes enthält jetzt das Ergebnis.

Endergebnis

Wir können die Zeilen zusammenpressen und in eine Funktion einwickeln, um die Verwendung zu erleichtern:

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

Oder, da es sinnvoll ist, dass class ein Faktor ist:

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

Sie verwenden beide Funktionen wie:

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

(Diese Methode zur Lösung dieses Problems ist gut, weil dadurch die explizite Iteration vermieden wird, was im Allgemeinen für R empfohlen wird, und das Generieren vieler Zwischenvektoren und Listen usw. vermieden wird. Außerdem ist es ziemlich nett, wie es in eine Zeile geschrieben werden kann.)

7
huon

Neben der Antwort von Roman könnte so etwas noch einfacher sein. Beachten Sie, dass ich es nicht getestet habe, weil ich momentan keinen Zugriff auf R habe.

# 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)
})

Die Funktion durchläuft die Werte in n_ho und gibt immer die Kategorie zurück, zu der der aktuelle Wert gehört. Wenn ein Wert von 1 erkannt wird, erhöhen wir die globale Variable index und fahren fort.

2
Paul Hiemstra
Data.frame[,'h_new_column'] <- as.integer(Data.frame[,'h_no'], breaks=c(1, 4, 7))
1
user2759975

Ansatz basierend auf der identifizierenden Anzahl von Gruppen (x in mapply) und ihrer Länge (y in 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
0
Ferroao

sie können zuerst eine leere Spalte zu Ihrem data.frame hinzufügen und dann Ihre Bedingungen für die neue Spalte angeben.

agtoexcel2$NONloan <- NA
agtoexcel2$NONloan[agtoexcel2$haveloan==2 & agtoexcel2$ifoloan==2 & agtoexcel2$both==0 ] <- 1
agtoexcel2$NONloan[agtoexcel2$haveloan==1 | agtoexcel2$ifoloan==1 | agtoexcel2$both==1 ] <- 0 
0
Seyma Kalay

Meiner Meinung nach ist die Verwendung von "cbind" die einfachste Möglichkeit, einem Datenrahmen in R eine Spalte hinzuzufügen. Unten ein Beispiel:

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