Добавление столбца в data.frame
У меня есть 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
Ответы
Ответ 1
Вы можете добавить столбец к своим данным, используя различные методы. Ниже приведены цитаты из раздела "Сведения" соответствующего справочного текста, [[.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
Ответ 2
Легко: ваш фрейм данных A
b <- A[,1]
b <- b==1
b <- cumsum(b)
Затем вы получите столбец b.
Ответ 3
Если я правильно понимаю вопрос, вы хотите определить, когда h_no
не увеличивается, а затем увеличить class
. (Я собираюсь пройтись по тому, как я решил эту проблему, в конце есть отдельная функция.)
За работой
На данный момент нам h_no
столбец 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
В R значения TRUE
и FALSE
в основном совпадают с 1
и 0
, поэтому, если мы получим накопленную сумму nonpos
, она увеличится на 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
(Этот метод решения этой проблемы хорош, потому что он избегает явной итерации, которая обычно рекомендуется для R, и избегает генерации большого количества промежуточных векторов, списков и т.д. А также он довольно изящен, как его можно записать в одну строку :))
Ответ 4
В дополнение к римскому ответу, что-то вроде этого может быть еще проще. Обратите внимание, что я не тестировал его, потому что сейчас у меня нет доступа к 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
и продолжаем.
Ответ 5
Data.frame[,'h_new_column'] <- as.integer(Data.frame[,'h_no'], breaks=c(1, 4, 7))
Ответ 6
Я считаю, что использование "cbind" - это самый простой способ добавить столбец к фрейму данных в R. Ниже приведен пример:
myDf = data.frame(index=seq(1,10,1), Val=seq(1,10,1))
newCol= seq(2,20,2)
myDf = cbind(myDf,newCol)
Ответ 7
Подход, основанный на определении количества групп (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
Ответ 8
вы можете сначала добавить пустой столбец в ваш data.frame, а затем указать условия для нового столбца,
'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 '