การใช้เฟรมข้อมูลหลายเฟรมและตารางค้นหาเพื่อทำหน้าที่ใน r

ฉันเพิ่งเริ่มใช้และมีชุดข้อมูลที่ซับซ้อน หวังว่าคำอธิบายของฉันจะถูกต้อง ฉันมีกรอบข้อมูลหลายกรอบที่ต้องใช้เพื่อทำสิ่งต่างๆ หลายอย่าง นี่คือตัวอย่างหนึ่ง ฉันมีกรอบข้อมูลสามกรอบ หนึ่งคือรายชื่อชนิดพันธุ์และรหัสที่เกี่ยวข้อง:

>df.sp
    Species Code
    Picea   PI
    Pinus   CA

อีกรายการคือรายชื่อพื้นที่ที่มีข้อมูลความอุดมสมบูรณ์ของชนิดพันธุ์ตามสถานที่ต่างๆ (dir) น่าเสียดายที่ลำดับของสายพันธุ์นั้นแตกต่างกัน

>df.site
Site  dir total  t01 t02 t03 t04
2         Total   PI  CA  AB  T
2     N    9      1   5   na na
2                 AB  ZI PI CA
2     S    5     2   2  1  4
3                 DD  EE AB YT
3     N    6     1   1  5   3
3                 AB YT  EE  DD
3     S     5     4   3  1   1

จากนั้นฉันก็มีกรอบข้อมูลของลักษณะที่สอดคล้องกับสายพันธุ์ด้วย:

>df.trait
Species  leaft  rootl
Picea     0.01    1.2
Pinus     0.02    3.5

ตัวอย่างของสิ่งหนึ่งที่ฉันต้องการทำคือรับค่าเฉลี่ยสำหรับแต่ละลักษณะ (df.trait$leaft และ df.trait$rootl) สำหรับสายพันธุ์ทั้งหมดต่อไซต์ (df.site$Site) และต่อตำแหน่งที่ตั้งของไซต์ (df.site$Site) ไซต์$ไซต์ N, S) ดังนั้นผลลัพธ์จะเป็นแถวแรก:

Site dir leaft rootl
2    N   0.015  2.35

ฉันหวังว่ามันจะสมเหตุสมผล มันซับซ้อนมากสำหรับฉันที่จะคิดว่าจะต้องทำอย่างไร ฉันได้ลองทำงานจากโพสต์นี้ และ สิ่งนี้ (และอื่น ๆ อีกมากมาย) แต่หลงทาง ขอบคุณสำหรับความช่วยเหลือ ชื่นชมจริงๆ.

อัปเดต: นี่คือตัวอย่างของ df.site จริง (ลดลง) โดยใช้ dput:

> dput(head(df.site))
structure(list(Site = c(2L, 2L, 2L, 2L, 2L, 2L), dir = c("rep17316", 
"N", "", "S", "", "SE"), total = c("Total", "9", "", 
"10", "", "9"), t01 = c("PI", "4", "CA", "1", "SILLAC", 
"3"), t02 = c("CXBLAN", "3", "ZIZAUR", "4", "OENPIL", "2"), 
    t03 = c("ZIZAPT", "1", "ECHPUR", "2", "ASCSYR", "2")), .Names = c("site", "dir", "total", "t01", "t02", "t03"), row.names = 2:7, class = "data.frame")

person KNN    schedule 12.02.2019    source แหล่งที่มา
comment
df.site ดูเหมือนจะอยู่ในสภาพที่แย่มากโดยที่คอลัมน์ไม่มีประเภทที่สอดคล้องกัน (เช่น คอลัมน์ total มีคำเช่น Total และตัวเลขเช่น 9 คอลัมน์ t04 มีคำเช่น "T" (เว้นแต่ว่าเป็นบูลีน TRUE?) สตริงเช่น "na" ซึ่งน่าจะไม่มีค่า NA ตัวเลข เช่น 4 และสตริงปกติ เช่น "CA" ขั้นตอนแรกจะต้องทำให้ข้อมูลเป็นรูปเป็นร่างอย่างแน่นอน คุณช่วยแชร์ชุดย่อยของ data frame นั้นกับ dput เพื่อให้คัดลอก/วางได้ และ เราสามารถดูคอลัมน์ได้ทุกประเภทใช่ไหม (ถ้าแชร์คอลัมน์อื่นๆ ด้วย dput() ก็คงจะดีไม่น้อย...)   -  person Gregor Thomas    schedule 12.02.2019
comment
ดูคำถามที่พบบ่อยที่ยอดเยี่ยมนี้ หากคุณต้องการความช่วยเหลือในการสร้างตัวอย่างที่ทำซ้ำได้ dput(droplevels(df.site[1:10, ]))น่าจะดี   -  person Gregor Thomas    schedule 12.02.2019
comment
อย่างไรก็ตาม คำถามที่ดีกว่าอาจเป็นการกลับไปที่วิธีที่คุณนำเข้า df.site และแก้ไขกระบวนการนำเข้า แทนที่จะพยายามแก้ไขข้อมูลที่ยุ่งเหยิงซึ่งเกิดขึ้น.... โดยไม่เห็นตัวอย่างแหล่งที่มา ก็ยากที่จะทราบว่าจะเป็นเช่นนั้นหรือไม่ งานจะน้อยลงหรือเปล่า.   -  person Gregor Thomas    schedule 12.02.2019
comment
ขอบคุณ ใช่ df.site เป็นฝันร้ายซึ่งเป็นส่วนหนึ่งของปัญหา นำเข้าอย่างถูกต้อง มันเป็นเพียงไฟล์ csv ที่ใช้งานได้ยาก ฉันเพิ่มเวอร์ชันลดขนาดโดยใช้ dput ตามที่แนะนำ   -  person KNN    schedule 12.02.2019
comment
ไม่เกี่ยวข้องกับ R แต่คอลัมน์ Species ตัวอย่างของคุณจะไม่ถูกตั้งชื่ออย่างเหมาะสมกว่า genus หรือไม่ :)   -  person DanTan    schedule 12.02.2019


คำตอบ (1)


คุณจะต้องถกเถียงข้อมูลของคุณให้อยู่ในรูปแบบที่สะอาดยิ่งขึ้นก่อน ฉันสมมติว่าโครงสร้างที่คุณ dput ด้านบนมีความสอดคล้องกันตลอดทั้ง df.site dataframe ของคุณ กล่าวคือมีการจับคู่แถว โดยแถวแรกระบุรหัสสายพันธุ์ ส่วนแถวที่สองมีการนับ (หรือข้อมูลที่รวบรวมอื่นๆ?)

เริ่มต้นด้วย df เป็น dataframe ที่คุณ dput() ด้านบน ฉันจะจำลองข้อมูลบางส่วนสำหรับ dataframe อีกสองอันก่อน:

df.sp <- data.frame(Species = paste0("species",1:8),
                    Code = c("ECHPUR", "CXBLAN", "ZIZAPT",
                             "CAMROT", "SILLAC", "OENPIL",
                             "ASCSYR", "ZIZAUR"))
df.sp
#>    Species   Code
#> 1 species1 ECHPUR
#> 2 species2 CXBLAN
#> 3 species3 ZIZAPT
#> 4 species4 CAMROT
#> 5 species5 SILLAC
#> 6 species6 OENPIL
#> 7 species7 ASCSYR
#> 8 species8 ZIZAUR

df.trait <- data.frame(Species = paste0("species",1:8),
                       leaft = round(runif(8, max=.2), 2),
                       rootl = round(runif(8, min=1, max=4),1))

df.trait
#>    Species leaft rootl
#> 1 species1  0.12   2.5
#> 2 species2  0.04   2.6
#> 3 species3  0.12   2.1
#> 4 species4  0.05   1.1
#> 5 species5  0.15   2.5
#> 6 species6  0.15   3.3
#> 7 species7  0.05   3.9
#> 8 species8  0.13   2.1

ขั้นแรก มาล้างข้อมูล df ด้วยการย้ายแถวที่สองที่มีข้อมูลที่รวบรวมไว้ และย้ายค่าเหล่านั้นไปยังคอลัมน์ชุดใหม่:

library(dplyr)

df.clean <- df %>% 
  #for each row, copy the direction and total from the following row
  mutate_at(vars(matches("dir|total")), lead) %>% 
  #create new columns for observed data and fill in values from following row
  mutate_at(vars(matches("t\\d+$")), 
            .funs = funs(n = lead(.))) %>% 
  #filter to rows with species code in t01
  filter(t01 %in% df.sp$Code) %>% 
  #drop "total" column (doesn't make sense after reshape)
  select(-total)

df.clean
#>   site dir    t01    t02    t03 t01_n t02_n t03_n
#> 1    2   N ECHPUR CXBLAN ZIZAPT     4     3     1
#> 2    2   S CAMROT ZIZAUR ECHPUR     1     4     2
#> 3    2  SE SILLAC OENPIL ASCSYR     3     2     2

ตอนนี้เรามีคอลัมน์ที่สอดคล้องกันสองชุดซึ่งมีรหัสชนิดและค่าตามลำดับ หากต้องการปรับรูปร่าง dataframe ให้เป็นรูปแบบยาว เราจะใช้ melt() จากแพ็คเกจ data.table ดูคำตอบของคำถามนี้สำหรับตัวอย่างอื่นๆ เกี่ยวกับวิธีการทำเช่นนี้

library(data.table)

df.clean <- df.clean %>% 
  setDT() %>% #convert to data.table to use data.tabel::melt
  melt(measure.vars = patterns("t\\d+$", "_n$"),
       value.name = c("Code", "Count") ) %>% 
  #drop "variable" column, which isn't needed
  select(-variable)

สุดท้าย เข้าร่วมสาม dataframes ของคุณ:

#merge tables together
df.summaries <- df.clean %>% 
  left_join(df.sp) %>% 
  left_join(df.trait)

ณ จุดนี้ คุณควรจะสามารถสรุปข้อมูลของคุณตามการจัดกลุ่มใดๆ ก็ตามที่คุณสนใจโดยใช้ group_by และ summarise

person DanTan    schedule 12.02.2019
comment
ว้าว. ขอบคุณที่สละเวลามากมายเพื่อช่วยฉัน! สิ่งนี้มีประโยชน์จริงๆ ฉันพยายามดิ้นรนมานานกว่าที่ฉันอยากจะยอมรับว่าพยายามทำให้สิ่งนี้อยู่ในรูปแบบที่ใช้งานได้ เข้าใกล้สิ่งที่ฉันต้องทำไปอีกก้าวใหญ่ ขอบคุณ, - person KNN; 13.02.2019