Як можна додати рядок до кадру даних в R?


129

Як R, як додати новий рядок до кадру даних, коли кадр даних уже ініціалізований?

Поки що я маю це:

df <- data.frame("hi", "bye")
names(df) <- c("hello", "goodbye")

#I am trying to add "hola" and "ciao" as a new row
de <- data.frame("hola", "ciao")

merge(df, de) # Adds to the same row as new columns

# Unfortunately, I couldn't find an rbind() solution that wouldn't give me an error

Будь-яка допомога буде вдячна


1
присвоїти імена deтеж. names(de) <- c("hello","goodbye")іrbind
Хашаа

3
Або в одному рядкуrbind(df, setNames(de, names(df)))
Rich Scriven

2
Це на самому ділі є область , яка баз R з тріском провалюється в, і протягом тривалого часу: stackoverflow.com/questions/13599197 / ...
thelatemail

1
@thelatemail не згоден. фрейми даних - це особлива структура в r. список списків із загальними динамічними іменами та атрибутами та методами. Я думаю, дуже очікується, що цього не можна rbind(data.frame(a = 1), data.frame(b = 2)).. чому б ти хотів? Я би сподівався, що це призведе до помилки незалежно. Це як merge'ing із випадковою byзмінною. І це 2015 рік, не всі встановлюють options(stringsAsFactors = FALSE)?
rawr

1
@rawr - звичайно, різні імена не повинні прив'язуватися, але R не може обробляти прив'язування імен до жодних імен, прив'язування імен до імен з однаковими розмірами або прив'язування нових даних для включення нових рівнів факторів. Я думаю, що це слабкість. Особливо, коли він може обробляти обов'язкові повторювані імена та всі імена NA. І налаштування stringsAsFactors=FALSEможе бути швидким виправленням, але зміна значень за замовчуванням, які інші люди мають встановити по-іншому, може справді зіпсувати день.
thelatemail

Відповіді:


131

Як @Khashaa та @Richard Scriven зазначають у коментарях, ви повинні встановити узгоджені назви стовпців для всіх кадрів даних, які ви хочете додати.

Отже, вам потрібно чітко оголосити назви стовпців для другого кадру даних de, а потім використовувати rbind(). Ви встановлюєте лише назви стовпців для першого кадру даних df:

df<-data.frame("hi","bye")
names(df)<-c("hello","goodbye")

de<-data.frame("hola","ciao")
names(de)<-c("hello","goodbye")

newdf <- rbind(df, de)

Дякую! Будь-яка ідея, як це виправити, якщо у мене немає оголошеного другого фрейму даних, але натомість кожне значення я хочу додати до нового рядка, що зберігається як змінна?
Rilcon42

8
Спробуйте: newdf<-rbind(df, data.frame(hello="hola", goodbye="ciao"))АБО зі змінною:newdf<-rbind(df, data.frame(hello=var1, goodbye=var2))
Parfait

109

Давайте спростимо:

df[nrow(df) + 1,] = c("v1","v2")

10
Це спричиняє проблеми при спробі додати новий рядок зі змішаними типами даних (деякі рядки, деякі числові). У такому випадку навіть числові значення перетворюються на рядок. Одне вирішення - додавати значення окремо, приблизно на зразок наступного (якщо припустити, що це 3 стовпчики): df[nrow(df) + 1, 1:2] = c("v1", "v2")і df[nrow(df), 3] = 100все ж це хороший момент щодо додавання нового рядка. Отже, +1
Студентська душа

17
Або використовуйте "список" замість "с".
Іцен де Бур

хороша ідея, але як я можу зробити, якщо я хочу вставити чи додати новий рядок першою позицією?
ПК Дарвіна

1
Спробував це за допомогою data.table, але повідомляє за допомогою nrow + 1 поза діапазоном.
Зубний Герман

1
@Arani вже є відповідь list(). Я відмінив вашу редакцію.
М--

41

Або, як надихнув @MatheusAraujo:

df[nrow(df) + 1,] = list("v1","v2")

Це дозволило б використовувати різні типи даних.


24

Там зараз add_row()від tibbleабо tidyverseпакетів.

library(tidyverse)
df %>% add_row(hello = "hola", goodbye = "ciao")

Невказані стовпці отримують NA.


Мені сподобався такий підхід, якщо ви дотримуєтесь філософії підводного світу. Інакше базовий синтаксис R - це навичка виживання, яка стане в нагоді, коли ви перебуваєте в середовищі, де у вас немає привілеїв імпортувати пакети. Особливо мені подобається відповідь, використовуючи простий синтаксис R з rbindі as.matrix нижче
Пабло Адамс,

17

Мені це подобається listзамість того, cщо він краще обробляє змішані типи даних. Додавання додаткового стовпчика до питання оригінального афіші:

#Create an empty data frame
df <- data.frame(hello=character(), goodbye=character(), volume=double())
de <- list(hello="hi", goodbye="bye", volume=3.0)
df = rbind(df,de, stringsAsFactors=FALSE)
de <- list(hello="hola", goodbye="ciao", volume=13.1)
df = rbind(df,de, stringsAsFactors=FALSE)

Зауважте, що необхідний додатковий контроль, якщо важливе значення має перетворення рядка / фактора.

Або використовуючи оригінальні змінні з рішенням MatheusAraujo / Ytsen de Boer:

df[nrow(df) + 1,] = list(hello="hallo",goodbye="auf wiedersehen", volume=20.2)

Зауважте, що це рішення не працює добре з рядками, якщо у фреймі даних немає існуючих даних.


Якщо helloі goodbyeв характері , в df, ви можете зробити наступне. Не обов’язково в списку використовувати імена. df <- data.frame(hello = "hi", goodbye = "bye", volume = 1,stringsAsFactors = FALSE); rbind(df, list("hola", "ciao", 100)).
джазурро

11

Не надзвичайно елегантно, але:

data.frame(rbind(as.matrix(df), as.matrix(de)))

З документації rbindфункції:

Для rbindімен стовпців беруться з першого аргументу з відповідними назвами: COLNAMES для матриці ...


Це рішення працює без необхідності вказувати стовпці для додавання, що набагато краще для додатків у великих наборах даних
Phil_T

1

Мені потрібно додати stringsAsFactors=FALSEпри створенні фрейму даних.

> df <- data.frame("hello"= character(0), "goodbye"=character(0))
> df
[1] hello   goodbye
<0 rows> (or 0-length row.names)
> df[nrow(df) + 1,] = list("hi","bye")
Warning messages:
1: In `[<-.factor`(`*tmp*`, iseq, value = "hi") :
  invalid factor level, NA generated
2: In `[<-.factor`(`*tmp*`, iseq, value = "bye") :
  invalid factor level, NA generated
> df
  hello goodbye
1  <NA>    <NA>
> 

.

> df <- data.frame("hello"= character(0), "goodbye"=character(0), stringsAsFactors=FALSE)
> df
[1] hello   goodbye
<0 rows> (or 0-length row.names)
> df[nrow(df) + 1,] = list("hi","bye")
> df[nrow(df) + 1,] = list("hola","ciao")
> df[nrow(df) + 1,] = list(hello="hallo",goodbye="auf wiedersehen")
> df
  hello         goodbye
1    hi             bye
2  hola            ciao
3 hallo auf wiedersehen
> 

1

stringsAsFactors=FALSEОбов’язково вкажіть під час створення фрейму даних:

> rm(list=ls())
> trigonometry <- data.frame(character(0), numeric(0), stringsAsFactors=FALSE)
> colnames(trigonometry) <- c("theta", "sin.theta")
> trigonometry
[1] theta     sin.theta
<0 rows> (or 0-length row.names)
> trigonometry[nrow(trigonometry) + 1, ] <- c("0", sin(0))
> trigonometry[nrow(trigonometry) + 1, ] <- c("pi/2", sin(pi/2))
> trigonometry
  theta sin.theta
1     0         0
2  pi/2         1
> typeof(trigonometry)
[1] "list"
> class(trigonometry)
[1] "data.frame"

Якщо не використовувати stringsAsFactors=FALSEпід час створення фрейму даних, це призведе до наступної помилки при спробі додати новий рядок:

> trigonometry[nrow(trigonometry) + 1, ] <- c("0", sin(0))
Warning message:
In `[<-.factor`(`*tmp*`, iseq, value = "0") :
  invalid factor level, NA generated

0

Існує простіший спосіб додавання запису з одного фрейму даних до іншого, якщо ви знаєте, що два фрейми даних мають однакові стовпці та типи. Для додавання одного рядка з xxдо yyпросто зробити наступне , де iє i«го рядка в xx.

yy[nrow(yy)+1,] <- xx[i,]

Просто як це. Ніяких брудних зв’язків. Якщо вам потрібно додати всі , xxщоб yy, потім або викликати петлю або скористатися можливостями послідовності г і зробити це:

zz[(nrow(zz)+1):(nrow(zz)+nrow(yy)),] <- yy[1:nrow(yy),]

0

Якщо ви хочете зробити порожній кадр даних та додати вміст у циклі, може допомогти наступне:

# Number of students in class
student.count <- 36

# Gather data about the students
student.age <- sample(14:17, size = student.count, replace = TRUE)
student.gender <- sample(c('male', 'female'), size = student.count, replace = TRUE)
student.marks <- sample(46:97, size = student.count, replace = TRUE)

# Create empty data frame
student.data <- data.frame()

# Populate the data frame using a for loop
for (i in 1 : student.count) {
    # Get the row data
    age <- student.age[i]
    gender <- student.gender[i]
    marks <- student.marks[i]

    # Populate the row
    new.row <- data.frame(age = age, gender = gender, marks = marks)

    # Add the row
    student.data <- rbind(student.data, new.row)
}

# Print the data frame
student.data

Сподіваюся, це допомагає :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.