R: потеря имен столбцов при добавлении строк в пустой фрейм данных


Я только начинаю с R и столкнулся со странным поведением: при вставке первой строки в пустой фрейм данных, оригинальные имена столбцов теряются.

пример:

a<-data.frame(one = numeric(0), two = numeric(0))
a
#[1] one two
#<0 rows> (or 0-length row.names)
names(a)
#[1] "one" "two"
a<-rbind(a, c(5,6))
a
#  X5 X6
#1  5  6
names(a)
#[1] "X5" "X6"

Как вы можете видеть, имена столбцов один и два заменить X5 и X6.

может кто-то пожалуйста, скажите мне, почему это происходит и есть ли правильный способ сделать это без потери колонка имена?

решение дробовика будет заключаться в том, чтобы сохранить имена во вспомогательном векторе, а затем добавить их обратно, когда закончите работу над фреймом данных.

спасибо

контекст:

Я создал функцию, которая собирает некоторые данные и добавляет их в качестве новой строки в таблицу данных полученных в качестве параметра. Я создаю фрейм данных, перебираю свои источники данных, передавая данные.кадр для каждого вызова функции должен быть заполнен его результатами.

8 57

8 ответов:

The rbind страницы справки указывает, что:

для ' cbind '(’rbind'), векторов нуля длина (включая ‘NULL’) игнорируются если результат не будет иметь нулевых строк (столбцов), для совместимости С. (Матрицы нулевой степени не встречаются в S3 и не игнорируются в р.)

так, на самом деле,a игнорируется в rbind инструкция. Не полностью игнорируется, кажется, потому что как это фрейм данных

почти сдался этому вопросу.

1) создать фрейм данных с stringsAsFactor значение FALSE или вы бежите прямо в следующем номере

2) не использовать rbind - не знаю, почему на земле это портит имена столбцов. просто сделайте это так:

df[nrow(df)+1,] <- c("d","gsgsgd",4)

df <- data.frame(a = character(0), b=character(0), c=numeric(0))

df[nrow(df)+1,] <- c("d","gsgsgd",4)

#Warnmeldungen:
#1: In `[<-.factor`(`*tmp*`, iseq, value = "d") :
#  invalid factor level, NAs generated
#2: In `[<-.factor`(`*tmp*`, iseq, value = "gsgsgd") :
#  invalid factor level, NAs generated

df <- data.frame(a = character(0), b=character(0), c=numeric(0), stringsAsFactors=F)

df[nrow(df)+1,] <- c("d","gsgsgd",4)

df
#  a      b c
#1 d gsgsgd 4

решение будет:

a <- rbind(a, data.frame(one = 5, two = 6))

?rbind утверждает, что слияние объектов требует совпадающих имен:

затем он принимает классы столбцы из первого фрейма данных, и сопоставляет столбцы по имени (а не по положению)

FWIW, альтернативный дизайн может иметь ваши функции, строящие векторы для двух столбцов, вместо привязки к фрейму данных:

ones <- c()
twos <- c()

измените векторы в ваших функциях:

ones <- append(ones, 5)
twos <- append(twos, 6)

повторите по мере необходимости, затем создайте свои данные.кадр на одном дыхании:

a <- data.frame(one=ones, two=twos)

Вы можете сделать это:

Дайте одну строку в начальный фрейм данных

 df=data.frame(matrix(nrow=1,ncol=length(newrow))

добавить новую строку и вынуть NAS

newdf=na.omit(rbind(newrow,df))

но будьте осторожны, что ваш newrow не имеет NAs или он будет стерт тоже.

Ура Агус

Я использую следующее решение, чтобы добавить строку в пустой фрейм данных:

d_dataset <- 
  data.frame(
    variable = character(),
    before = numeric(),
    after = numeric(),
    stringsAsFactors = FALSE)

d_dataset <- 
  rbind(
    d_dataset,
      data.frame(
        variable = "test",
        before = 9,
        after = 12,
        stringsAsFactors = FALSE))  

print(d_dataset)

variable before after  
1     test      9    12

HTH.

С уважением

Георг

один из способов сделать эту работу в целом и с наименьшим количеством повторного ввода имен столбцов заключается в следующем. Этот метод не требует взлома NA или 0.

rs <- data.frame(i=numeric(), square=numeric(), cube=numeric())
for (i in 1:4) {
    calc <- c(i, i^2, i^3)
    # append calc to rs
    names(calc) <- names(rs)
    rs <- rbind(rs, as.list(calc))
}

RS будет иметь правильные имена

> rs
    i square cube
1   1      1    1
2   2      4    8
3   3      9   27
4   4     16   64
> 

другой способ сделать это более аккуратно использовать данные.таблица:

> df <- data.frame(a=numeric(0), b=numeric(0))
> rbind(df, list(1,2)) # column names are messed up
>   X1 X2
> 1  1  2

> df <- data.table(a=numeric(0), b=numeric(0))
> rbind(df, list(1,2)) # column names are preserved
   a b
1: 1 2

обратите внимание, что данные.таблица также является данными.рамка.

> class(df)
"data.table" "data.frame"

вместо построения данных.кадр с numeric(0) Я использую as.numeric(0).

a<-data.frame(one=as.numeric(0), two=as.numeric(0))

это создает дополнительную начальную строку

a
#    one two
#1   0   0

привязать дополнительные строки

a<-rbind(a,c(5,6))
a
#    one two
#1   0   0
#2   5   6

затем используйте отрицательную индексацию, чтобы удалить первую (фиктивную) строку

a<-a[-1,]
a

#    one two
#2   5   6

Примечание: это портит индекс (крайний слева). Я не понял, как предотвратить это (кто-нибудь еще?), но в большинстве случаев это, вероятно, не имеет значения.