menggunakan beberapa bingkai data dan tabel pencarian untuk menjalankan fungsi di r

Saya baru mengenal r dan memiliki kumpulan data yang rumit, jadi harap penjelasan saya benar. Saya memiliki beberapa bingkai data yang perlu saya gunakan untuk melakukan serangkaian hal. Ini salah satu contohnya. Saya memiliki tiga bingkai data. Salah satunya adalah daftar nama spesies dan kode terkait:

>df.sp
    Species Code
    Picea   PI
    Pinus   CA

Lainnya adalah daftar lokasi dengan data kelimpahan spesies untuk berbagai lokasi (dir). Sayangnya, urutan spesiesnya berbeda.

>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

Kemudian saya juga memiliki kerangka data sifat-sifat yang sesuai dengan spesiesnya:

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

Contoh satu hal yang ingin saya lakukan adalah mendapatkan nilai rata-rata untuk setiap sifat (df.trait$leaft dan df.trait$rootl) untuk semua spesies per situs (df.site$Site) dan per lokasi situs (df. situs$Situs N, S). Jadi hasilnya untuk baris pertama:

Site dir leaft rootl
2    N   0.015  2.35

Saya harap itu masuk akal. Sangat rumit bagi saya untuk memikirkan bagaimana cara melakukannya. Saya telah mencoba bekerja dari postingan ini dan ini (dan banyak lainnya) tetapi hilang. Terima kasih untuk bantuannya. Sangat dihargai.

PEMBARUAN: Berikut adalah contoh df.site sebenarnya (dikurangi) menggunakan 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 sumber
comment
df.site terlihat berada dalam kondisi yang sangat buruk ketika kolom-kolomnya tidak memiliki tipe yang konsisten (misalnya, kolom total memiliki kata-kata seperti Total dan angka-angka seperti 9, kolom t04 memiliki kata-kata seperti "T" (kecuali itu boolean BENAR?), string seperti "na" yang mungkin berisi nilai yang hilang NA, angka seperti 4, dan string biasa seperti "CA". Langkah pertama pastinya adalah membuat data tersebut berbentuk. Bisakah Anda membagikan subset bingkai data tersebut dengan dput sehingga dapat disalin/ditempel dan kita dapat melihat semua tipe kolom? (Berbagi yang lain dengan dput() juga akan menyenangkan...)   -  person Gregor Thomas    schedule 12.02.2019
comment
Lihat FAQ yang luar biasa ini jika Anda memerlukan bantuan untuk membuat contoh yang dapat direproduksi. dput(droplevels(df.site[1:10, ])) mungkin bagus.   -  person Gregor Thomas    schedule 12.02.2019
comment
Namun, pertanyaan yang lebih baik adalah kembali ke cara Anda mengimpor df.site dan memperbaiki proses impor daripada mencoba memperbaiki data kacau yang dihasilkan.... tanpa melihat contoh sumbernya, sulit untuk mengetahui apakah itu akan terjadi. menjadi kurang bekerja atau tidak.   -  person Gregor Thomas    schedule 12.02.2019
comment
Terima kasih. Ya, df.site adalah mimpi buruk, yang merupakan bagian dari masalahnya. Itu diimpor dengan benar, itu hanya file csv yang sulit untuk digunakan. Saya menambahkan versi yang diperkecil menggunakan dput seperti yang disarankan.   -  person KNN    schedule 12.02.2019
comment
Tidak terkait dengan R, tetapi bukankah contoh kolom Species Anda akan lebih tepat diberi nama genus? :)   -  person DanTan    schedule 12.02.2019


Jawaban (1)


Anda harus terlebih dahulu mengatur data Anda menjadi bentuk yang lebih bersih. Saya berasumsi struktur yang Anda dput di atas konsisten di seluruh kerangka data df.site Anda; yaitu baris berpasangan, baris pertama menentukan kode spesies, baris kedua berisi hitungan (atau data lain yang dikumpulkan?).

Dimulai dengan df sebagai kerangka data yang Anda dput() di atas, pertama-tama saya akan mensimulasikan beberapa data untuk dua kerangka data lainnya:

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

Pertama, mari kita bersihkan df dengan memindahkan baris kedua yang berisi data yang dikumpulkan, dan memindahkan nilai tersebut ke dalam kumpulan kolom baru:

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

Kami sekarang memiliki dua set kolom terkait yang masing-masing memiliki kode spesies dan nilai. Untuk membentuk kembali kerangka data menjadi bentuk panjang kita akan menggunakan melt() dari paket data.table. Lihat respons terhadap pertanyaan ini untuk contoh lain tentang cara melakukan hal ini.

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)

Terakhir, gabungkan tiga kerangka data Anda:

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

Pada titik ini Anda seharusnya dapat meringkas data berdasarkan pengelompokan apa pun yang Anda minati menggunakan group_by dan summarise.

person DanTan    schedule 12.02.2019
comment
Wow. Terima kasih telah menghabiskan begitu banyak waktu untuk mencoba membantu saya! Ini sungguh, sangat membantu. Saya telah berjuang lebih lama daripada yang ingin saya akui saat mencoba menjadikan ini format yang bisa digunakan. Satu langkah besar lebih dekat dengan apa yang perlu saya lakukan. Terima kasih, - person KNN; 13.02.2019