Làm thế nào có thể thêm một hàng vào khung dữ liệu trong R?


129

Trong R, làm thế nào để bạn thêm một hàng mới vào khung dữ liệu sau khi khung dữ liệu đã được khởi tạo?

Cho đến nay tôi có điều này:

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

Bất kỳ trợ giúp sẽ được đánh giá cao


1
gán tên cho dequá. names(de) <- c("hello","goodbye")rbind
Khashaa

3
Hoặc trong một dòngrbind(df, setNames(de, names(df)))
Rich Scriven

2
Đây thực sự là một khu vực mà căn cứ R thất bại thảm hại và đã có từ lâu: stackoverflow.com/questions/13599197/
Kẻ

1
@thelHRail không đồng ý. khung dữ liệu là một cấu trúc đặc biệt trong r. một danh sách các danh sách với các tên và các thuộc tính và phương thức phổ biến. Tôi nghĩ rằng người ta không thể mong đợi rbind(data.frame(a = 1), data.frame(b = 2)).. tại sao bạn lại muốn như vậy? Tôi hy vọng rằng sẽ ném một lỗi bất kể. Nó giống như merge'với một bybiến ngẫu nhiên . Và đây là năm 2015, không phải ai cũng đặt ra options(stringsAsFactors = FALSE)sao?
rawr

1
@rawr - chắc chắn, các tên khác nhau không nên bị ràng buộc, nhưng R không thể xử lý ràng buộc không có tên với không tên, ràng buộc tên không có tên có cùng kích thước hoặc ràng buộc dữ liệu mới để kết hợp các cấp yếu tố mới. Tôi nghĩ đó là một điểm yếu. Đặc biệt khi nó có thể xử lý các tên lặp lại ràng buộc và tất cả các tên NA. Và cài đặt stringsAsFactors=FALSEcó thể là một sửa chữa nhanh chóng, nhưng thay đổi mặc định mà người khác sẽ đặt khác đi thực sự có thể làm hỏng một ngày.
thelHRail

Câu trả lời:


131

Giống như @Khashaa và @Richard Scriven chỉ ra trong các bình luận, bạn phải đặt tên cột nhất quán cho tất cả các khung dữ liệu bạn muốn nối.

Do đó, bạn cần khai báo rõ ràng tên cột cho khung dữ liệu thứ hai de, sau đó sử dụng rbind(). Bạn chỉ đặt tên cột cho khung dữ liệu đầu tiên , 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)

Cảm ơn! Bất kỳ ý tưởng nào để khắc phục điều này nếu tôi không có một khung dữ liệu thứ hai được khai báo, nhưng thay vào đó, mỗi giá trị tôi muốn thêm vào một hàng mới được lưu dưới dạng một biến?
Rilcon42

8
Thử: newdf<-rbind(df, data.frame(hello="hola", goodbye="ciao"))HOẶC với biến:newdf<-rbind(df, data.frame(hello=var1, goodbye=var2))
Parfait

108

Hãy làm cho nó đơn giản:

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

9
Điều này gây ra vấn đề khi cố gắng thêm một hàng mới với các loại dữ liệu hỗn hợp (một số chuỗi, một số số). Trong trường hợp như vậy, ngay cả các giá trị số được chuyển đổi thành chuỗi. Một cách giải quyết là thêm các giá trị riêng, một cái gì đó như sau (giả sử có 3 cột): df[nrow(df) + 1, 1:2] = c("v1", "v2")df[nrow(df), 3] = 100Nhưng nó vẫn là một điểm tốt về việc thêm hàng mới. Vì vậy, +1
Linh hồn sinh viên

17
Hoặc sử dụng "danh sách" thay vì "c".
Ytsen de Boer

ý tưởng hay, nhưng tôi có thể làm gì nếu tôi muốn chèn hoặc thêm một hàng mới vào vị trí đầu tiên?
Darwin PC

1
Đã thử điều này với data.table nhưng cho biết với nrow + 1 nằm ngoài phạm vi.
Herman Toothrot 17/10/18

1
@Arani đã có câu trả lời với list(). Tôi hoàn nguyên chỉnh sửa của bạn.
M--

41

Hoặc, như được truyền cảm hứng bởi @MeditusAraujo:

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

Điều này sẽ cho phép các loại dữ liệu hỗn hợp.


24

Bây giờ add_row()từ gói tibblehoặc tidyverse.

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

Các cột không xác định có được một NA.


Tôi thích cách tiếp cận này nếu bạn tuân theo triết lý gọn gàng. Mặt khác, cú pháp R cơ bản là một kỹ năng sinh tồn có ích khi bạn ở trong môi trường mà bạn không có đặc quyền để nhập các gói. Tôi đặc biệt thích câu trả lời bằng cách sử dụng cú pháp R đơn giản với rbindas.matrix bên dưới
Pablo Adames

17

Tôi thích listthay cvì bởi vì nó xử lý các loại dữ liệu hỗn hợp tốt hơn. Thêm một cột bổ sung cho câu hỏi của người đăng ban đầu:

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

Lưu ý rằng một số điều khiển bổ sung là bắt buộc nếu chuyển đổi chuỗi / yếu tố là quan trọng.

Hoặc sử dụng các biến ban đầu với giải pháp từ MatheusAraujo / Ytsen de Boer:

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

Lưu ý rằng giải pháp này không hoạt động tốt với các chuỗi trừ khi có dữ liệu hiện có trong khung dữ liệu.


Nếu hellogoodbyelà nhân vật trong df, bạn có thể làm như sau. Bạn không nhất thiết phải sử dụng tên trong danh sách. df <- data.frame(hello = "hi", goodbye = "bye", volume = 1,stringsAsFactors = FALSE); rbind(df, list("hola", "ciao", 100)).
jazzurro

11

Không thanh lịch khủng khiếp, nhưng:

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

Từ tài liệu của rbindchức năng:

Đối với rbindtên cột được lấy từ đối số đầu tiên với tên thích hợp: colnames cho ma trận ...


Giải pháp này hoạt động mà không cần chỉ định các cột cần thêm, tốt hơn nhiều cho các ứng dụng trên các bộ dữ liệu lớn
Phil_T

1

Tôi cần thêm stringsAsFactors=FALSEkhi tạo dataframe.

> 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

Đảm bảo chỉ định stringsAsFactors=FALSEkhi tạo khung dữ liệu:

> 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"

Không sử dụng stringsAsFactors=FALSEkhi tạo dataframe sẽ dẫn đến lỗi sau khi cố gắng thêm hàng mới:

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

0

Có một cách đơn giản hơn để nối một bản ghi từ một khung dữ liệu này sang một khung dữ liệu khác NẾU bạn biết rằng hai tệp dữ liệu này có chung các cột và loại. Để thêm một hàng từ xxđể yychỉ làm những điều sau đây mà ii'thứ hàng trong xx.

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

Đơn giản như vậy. Không có ràng buộc lộn xộn. Nếu bạn cần nối thêm tất cả xxvào yy, thì hãy gọi một vòng lặp hoặc tận dụng các khả năng trình tự của R và thực hiện điều này:

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

0

Nếu bạn muốn tạo một khung dữ liệu trống và thêm nội dung trong một vòng lặp, những điều sau đây có thể giúp:

# 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

Hy vọng nó giúp :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.