วิธีง่ายๆ ในการเพิ่มการสังเกตไปยัง dataframe ที่มีอยู่?

ฉันมี dataframe ที่มีอยู่ซึ่งฉันต้องการเพิ่มการสังเกตที่อัปเดต ฉันสามารถระบุการสังเกตที่อัปเดตเหล่านี้ได้ด้วย ID และตัวแปรจุดเวลา ฉันได้ลองลบการสังเกตที่ล้าสมัยออกจาก dataframe ที่มีอยู่แล้วลองใช้ฟังก์ชัน merge() เพื่อผสานกับ dataframe โดยมีเพียงการสังเกตที่อัปเดต แต่ฉันได้รับคอลัมน์ที่ซ้ำกัน มีวิธีที่สง่างามในการทำเช่นนี้ (โดยเฉพาะการใช้ dplyr หรือไม่)

นี่คือตัวอย่างสิ่งที่ฉันอยากทำ: สมมติว่าฉันมี df เรียกว่าแบบฝึกหัด

practice

ID     Time  score 1 score 2 
 1   hour 1        3       7
 1   hour 2        4       2
 2   hour 1        3       4

สมมติว่าฉันต้องการเปลี่ยนตัวแปรคะแนน 1 สำหรับการสังเกตครั้งที่สาม (ซึ่ง ID==2 และเวลา=="ชั่วโมง 1") จาก 3 เป็น 5

สิ่งที่ฉันได้ลองคือสร้าง dataframe ใหม่ที่เรียกว่า Practice1:

ID     Time  score 1  score 2 
 1   hour 1        3        7
 1   hour 2        4        2

ซึ่งจะลบการสังเกตครั้งที่สามออก จากนั้นจึงสร้าง dataframe ใหม่ด้วยการสังเกตที่ถูกต้อง เรียกว่า Practice2:

   ID     Time  score 1  score 2 
    2   hour 1        3        4

ฉันได้ลองทำอะไรแบบนี้:

Practice3 <- merge(practice2, practice1, by = "ID", all = T)

อย่างไรก็ตาม ฉันจะได้รับคอลัมน์ที่ซ้ำกัน และเมื่อฉันพยายามรวมตัวแปรหลายตัวในคำสั่ง by= ในฟังก์ชันผสาน ฉันได้รับข้อผิดพลาดนี้:

Error in fix.by(by.x, x) : 'by' must specify a uniquely valid column

ข้อใดอาจเป็นเพราะลักษณะของข้อมูลตามยาว?

ขอบคุณ


person baldirony    schedule 19.04.2017    source แหล่งที่มา
comment
โปรดระบุข้อมูลตัวอย่าง stackoverflow.com/questions/5963269/   -  person neilfws    schedule 20.04.2017
comment
ขออภัย ฉันพยายามเพิ่มข้อมูลตัวอย่างในการแก้ไข   -  person baldirony    schedule 20.04.2017
comment
@ G5W ใช่แน่นอน; ฉันแก้ไขโพสต์ตามนั้น ขอบคุณ.   -  person baldirony    schedule 20.04.2017


คำตอบ (3)


คุณสามารถทดแทนตัวแปรในกรอบข้อมูลได้ เช่น.:

practice[["Score 1"]][practice$ID == 2 & practice$Time=="hour 1"] <- 5
person thc    schedule 20.04.2017
comment
หรือ practice[practice$ID == 2 & practice$Time == "hour 1", "score 1"] <- 5 เพื่อทำให้ง่ายขึ้นเล็กน้อย - person thelatemail; 20.04.2017
comment
นอกจากนี้ คุณต้องอ้างอิง practice$Time แทนที่จะเป็นเพียง Time - person thelatemail; 20.04.2017
comment
ขอบคุณ นี่อาจเป็นสิ่งที่ฉันต้องการ ฉันคิดว่าวงเล็บคู่จะใช้เมื่อต้องจัดการกับรายการเท่านั้น - person baldirony; 20.04.2017
comment
@baldirony - data.frames เป็นรายการ - person thelatemail; 20.04.2017
comment
@thelatemail โอ้ dfs เป็นแค่รายการ object = 1 เหรอ? - person baldirony; 20.04.2017
comment
@baldirony - data.frames เป็นรายการที่แต่ละคอลัมน์เป็นรายการที่มีความยาวเท่ากัน เปรียบเทียบ as.list(mtcars) กับ mtcars - person thelatemail; 20.04.2017
comment
ใช่ data.frames เป็นคลาสที่ได้รับมาจากรายการ และสืบทอดวิธีการรายการทั้งหมด: programiz.com /r-การเขียนโปรแกรม/สืบทอด - person thc; 20.04.2017

นี่คือการอัปเดตโดยใช้ dplyr::mutate หมายเหตุ: ฉันเปลี่ยนชื่อคอลัมน์เพื่อลบช่องว่าง

library(dplyr)
practice %>% 
  mutate(score1 = ifelse(ID == 2 & Time == "hour 1", 5, score1))
person neilfws    schedule 20.04.2017

หากคุณมีข้อมูลใหม่ใน data.frame อยู่แล้ว คุณสามารถใช้ anti_join เพื่อลบเคสเก่าออก จากนั้นใช้ bind_rows เพื่อเพิ่มเคสใหม่:

library(dplyr)

practice <- read.table(text = 'ID     Time  score1 score2 
                                1    hour1       3      7
                                1    hour2       4      2
                                2    hour1       3      4', 
                       header = TRUE, stringsAsFactors = FALSE)

practice2 <- read.table(text = 'ID     Time  score1  score2 
                                 2    hour1       5       5', 
                        header = TRUE, stringsAsFactors = FALSE)

practice %>% 
    anti_join(practice2, by = c('ID', 'Time')) %>% 
    bind_rows(practice2)

#>   ID  Time score1 score2
#> 1  1 hour2      4      2
#> 2  1 hour1      3      7
#> 3  2 hour1      5      5

อย่างไรก็ตาม วิธีนี้จะใช้งานไม่ได้หาก practice2 ไม่มีคอลัมน์ ในกรณีนี้ คุณสามารถใช้ coalesce เพื่อเขียนทับค่าเก่าด้วยค่าใหม่ได้:

left_join(practice, practice2, by = c('ID', 'Time')) %>% 
    mutate(score1 = coalesce(score1.y, score1.x), 
           score2 = coalesce(score2.y, score2.x)) %>% 
    select(-contains('.'))

#>   ID  Time score1 score2
#> 1  1 hour1      3      7
#> 2  1 hour2      4      2
#> 3  2 hour1      5      5
person alistaire    schedule 20.04.2017