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
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]
oderx[[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
$
behandeltx
als Liste
my.dataframe$new.col <- a.vector
Wenn
[
und[[
mit zwei Indizes (x[i, j]
undx[[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
Leicht: Ihr Datenrahmen ist A
b <- A[,1]
b <- b==1
b <- cumsum(b)
Dann erhalten Sie die Spalte b.
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.)
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.
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.)
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.
Data.frame[,'h_new_column'] <- as.integer(Data.frame[,'h_no'], breaks=c(1, 4, 7))
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
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
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)