Pertanyaan Cara menulis loop “for” loop di R menggunakan sintaks dplyr


Saya memiliki blok kode yang luas yang telah saya tulis menggunakan sintaks dplyr di R. Namun, saya mencoba untuk menempatkan kode itu dalam satu lingkaran, sehingga pada akhirnya saya dapat membuat beberapa file output dibandingkan dengan hanya satu. Sayangnya, saya tampaknya tidak dapat melakukannya.

Untuk tujuan ilustrasi mengenai masalah saya, mari kita lihat dataset "iris" yang umum digunakan di R:

      > data("iris")
      > str(iris)
      'data.frame': 150 obs. of  5 variables:
      $ Sepal.Length: num  
      $ Sepal.Width : num  
      $ Petal.Length: num  
      $ Petal.Width : num  
      $ Species     : Factor w/ 3 levels "setosa","versicolor","virginica"

Katakanlah saya ingin menyelamatkan kelopak rata-rata. Panjang spesies "versicolor". Kode dplyr dapat terlihat seperti berikut:

    MeanLength2 <- iris %>% filter(Species=="versicolor")
                       %>% summarize(mean(Petal.Length)) %>% print()

Yang akan memberikan nilai berikut:

      mean(Petal.Length)
    1               4.26

Mari mencoba membuat lingkaran untuk mendapatkan panjang kelopak rata-rata untuk semua spesies.

Dari apa yang saya ketahui tentang loop, saya ingin melakukan sesuatu seperti ini:

     for (i in unique(iris$Species))
      {
       iris %>% filter(iris$Species==unique(iris$Species)[i]) %>%
        summarize(mean(iris$Petal.Length)) %>% print()
        print(i) 
       }

Untuk beberapa alasan, saya harus menentukan frame data dan kolom di dalam loop, yang umumnya tidak terjadi saat menggunakan fungsionalitas perpipaan dari dplyr. Saya berasumsi bahwa ini adalah indikasi masalah.

Bagaimanapun, kode di atas memberikan output sebagai berikut:

          mean(iris$Petal.Length)
     1                   3.758
     [1] "setosa"
          mean(iris$Petal.Length)
     1                   3.758
     [1] "versicolor"
          mean(iris$Petal.Length)
     1                   3.758
     [1] "virginica"  

Jadi, kode ini mengeluarkan 3.758 tiga kali, yang merupakan panjang kelopak rata-rata di semua spesies dalam kumpulan data. Ini menunjukkan bahwa kode "filter" tidak berfungsi seperti yang diharapkan. Dari apa yang bisa saya katakan, tampaknya lingkaran itu sendiri berfungsi sebagaimana dimaksud, karena ketiga nama spesies yang unik dicetak dalam hasil akhirnya.

Bagaimana seseorang bisa melakukan sesuatu seperti ini dengan menggunakan untuk loop? Saya memahami bahwa latihan khusus ini tidak memerlukan penggunaan loop mewah karena seseorang dapat dengan mudah mendapatkan kelopak panjang rata-rata dari semua spesies dengan menggunakan, misalnya, fungsi "group_by" dalam dplyr, tetapi saya mencari keluaran dekat dengan 100 tabel dan file PDF unik dengan dataset yang saya kerjakan dan mengetahui cara menggunakan untuk loop akan sangat membantu untuk tujuan itu.


5
2017-09-01 20:35


asal


Jawaban:


Seperti yang saya sebutkan di komentar saya, jika Anda benar-benar membutuhkan hasil yang terpisah, itu mungkin akan lebih mudah digunakan group_by lalu split() hasil:

iris %>% 
  group_by(Species) %>% 
  summarise(mn = mean(Petal.Length)) %>% 
  split(.,.$Species)

$setosa
# A tibble: 1 × 2
  Species    mn
   <fctr> <dbl>
1  setosa 1.462

$versicolor
# A tibble: 1 × 2
     Species    mn
      <fctr> <dbl>
1 versicolor  4.26

$virginica
# A tibble: 1 × 2
    Species    mn
     <fctr> <dbl>
1 virginica 5.552

5
2017-09-01 20:43



Sangat disayangkan bahwa kode Anda tidak menimbulkan kesalahan apa pun. Jika Anda menjalankan kode baris demi baris, Anda akan mengerti apa yang saya katakan. Untuk contoh ini saya akan memilih iterasi pertama dari loop Anda, mari ganti i untuk "setosa":

> iris  %>% filter(iris$Species == unique(iris$Species)["setosa"])
[1] Sepal.Length Sepal.Width  Petal.Length Petal.Width  Species     
<0 rows> (or 0-length row.names)

Filter Anda menghasilkan bingkai data tanpa observasi, jadi tidak ada titik di depan, tetapi untuk contoh ini, mari jalankan sisa kode:

> iris  %>% filter(iris$Species == unique(iris$Species)["setosa"]) %>%  
+ summarize(mean(iris$Petal.Length))
  mean(iris$Petal.Length)
1                   3.758

Apa yang terjadi adalah Anda memanggil iris kumpulan data dari dalam kode Anda, contoh yang lebih jelas adalah:

> filter(iris, iris$Species == unique(iris$Species)["setosa"]) %>% 
+ summarize(mean(mtcars$cyl))
  mean(mtcars$cyl)
1           6.1875

Itulah mengapa Anda tidak mendapatkan jawaban yang Anda harapkan, filter Anda tidak berfungsi dan Anda mendapat statistik ringkasan dari kumpulan data lain.

Seperti yang disebutkan TJ Mahr, kode Anda tanpa menentukan dataset berjalan dengan baik:

> for (i in unique(iris$Species))
+ {
+     iris %>% filter(Species==i) %>%
+         summarize(mean(Petal.Length)) %>% print()
+     print(i) 
+ }
  mean(Petal.Length)
1              1.462
[1] "setosa"
  mean(Petal.Length)
1               4.26
[1] "versicolor"
  mean(Petal.Length)
1              5.552
[1] "virginica"

saya harap ini membantu


3
2017-09-02 01:44