title: R - Rotate coordinates in dataframe based on varying angles and origin
body: <p>I have a dataframe <code>data</code> with several columns including ID <code>Image</code> (repeated for several rows) and X <code>CenterX_um</code> and Y <code>CenterY_um</code> coordinate (different for each row).</p>
  <p>I want to rotate the X, Y coordinates based on an angle and origin that are specific for each ID. I also have this info on a separate dataframe <code>rotation_info</code>.</p>
  <p>I have tried the <code>rearrr::rotate_2d</code> function but it doesn't let me specify the angle and origin. Rather, it wants to use the same angle and origin for all.</p>
  <p>Any clues?</p>
  <p>Here is a subset of each dataframe:</p>
  <pre><code>data &lt;- structure(list(Image = c(&quot;P112_SOD1_scene-01_roi1&quot;, &quot;P112_SOD1_scene-01_roi1&quot;, &quot;P112_SOD1_scene-01_roi1&quot;, &quot;P112_SOD1_scene-03_roi1&quot;,
                           &quot;P112_SOD1_scene-03_roi1&quot;, &quot;P112_SOD1_scene-03_roi1&quot;, &quot;P112_SOD1_scene-08_roi1&quot;, &quot;P112_SOD1_scene-08_roi1&quot;, 
                           &quot;P112_SOD1_scene-14_roi1&quot;, &quot;P112_SOD1_scene-14_roi1&quot;, &quot;P112_WT_scene-13_roi1&quot;, &quot;P112_WT_scene-13_roi1&quot;),
                 Area_pixel2 = c(6172L, 2804L, 4133L, 1547L, 9224L, 5133L, 4311L, 2740L, 2610L, 3802L, 5129L, 4106L),
                 Area_um2 = c(318.03702442715, 144.48733254921, 212.96938139297, 79.715372130394, 475.30355044005, 264.49838729497, 222.14154444352, 
                              141.18947617148, 134.49070540422, 195.91328043941, 264.29227127136, 211.57809823361),
                 CenterX_um = c(1149.8904493589, 1126.4609300602, 1100.8211294593, 1024.1176019595, 993.32875148771, 964.51498442025, 874.9485394368,
                                843.03397382692, 1457.7886911485, 1359.4372824824, 1549.4154976822, 1614.8843949665),
                 CenterY_um = c(65.734010569428, 87.806098466489, 121.24362888879, 344.12182158201, 349.1125830895, 378.36327230154, 222.10103046474,
                                236.8534704986, 524.97197144378, 536.26329031132, 101.93303030628, 103.3766130805),
                 Circularity = c(0.70514719268137, 0.73725777209061, 0.55904614141807, 0.64491724919754, 0.72628772170604, 0.68836548793912,
                                 0.80455000787307, 0.75794971514553, 0.58945714820048, 0.75891540252167, 0.63520099709918, 0.79151119246911),
                 Compactness = c(0.66065335617958, 0.64189735971181, 0.53383026406418, 0.53076228622962, 0.76004630952984, 0.72584335956662,
                                 0.81606076244974, 0.77264654886067, 0.51250290104024, 0.78515382913133, 0.66035724052464, 0.80977712999347)),
            row.names = c(1L, 2L, 3L, 1505L, 1506L, 1507L, 8500L, 8501L, 15689L, 15690L, 30001L, 30002L), class = &quot;data.frame&quot;)
  
  data
  #                        Image Area_pixel2  Area_um2 CenterX_um CenterY_um Circularity Compactness
  #1     P112_SOD1_scene-01_roi1        6172 318.03702  1149.8904   65.73401   0.7051472   0.6606534
  #2     P112_SOD1_scene-01_roi1        2804 144.48733  1126.4609   87.80610   0.7372578   0.6418974
  #3     P112_SOD1_scene-01_roi1        4133 212.96938  1100.8211  121.24363   0.5590461   0.5338303
  #1505  P112_SOD1_scene-03_roi1        1547  79.71537  1024.1176  344.12182   0.6449172   0.5307623
  #1506  P112_SOD1_scene-03_roi1        9224 475.30355   993.3288  349.11258   0.7262877   0.7600463
  #1507  P112_SOD1_scene-03_roi1        5133 264.49839   964.5150  378.36327   0.6883655   0.7258434
  #8500  P112_SOD1_scene-08_roi1        4311 222.14154   874.9485  222.10103   0.8045500   0.8160608
  #8501  P112_SOD1_scene-08_roi1        2740 141.18948   843.0340  236.85347   0.7579497   0.7726465
  #15689 P112_SOD1_scene-14_roi1        2610 134.49071  1457.7887  524.97197   0.5894571   0.5125029
  #15690 P112_SOD1_scene-14_roi1        3802 195.91328  1359.4373  536.26329   0.7589154   0.7851538
  #30001   P112_WT_scene-13_roi1        5129 264.29227  1549.4155  101.93303   0.6352010   0.6603572
  #30002   P112_WT_scene-13_roi1        4106 211.57810  1614.8844  103.37661   0.7915112   0.8097771
  </code></pre>
  <pre><code>rotation_info &lt;- structure(list(Image = c(&quot;P112_SOD1_scene-01_roi1&quot;, &quot;P112_SOD1_scene-03_roi1&quot;, 
  &quot;P112_SOD1_scene-08_roi1&quot;, &quot;P112_SOD1_scene-14_roi1&quot;, &quot;P112_WT_scene-13_roi1&quot;
  ), Angle = c(199.289658091447, 202.184697711029, 158.990932730799, 
  180.612494033135, 15.223442470483), CC_X = c(989.039056641, 970.652055588, 
  1104.355063245, 781.334044746, 1034.893059267), CC_Y = c(792.457045383, 
  798.359045721, 940.915053885, 747.057042783, 709.829040651)), row.names = c(NA, 
  -5L), class = &quot;data.frame&quot;)
  
  rotation_info
  #                    Image     Angle      CC_X     CC_Y
  #1 P112_SOD1_scene-01_roi1 199.28966  989.0391 792.4570
  #2 P112_SOD1_scene-03_roi1 202.18470  970.6521 798.3590
  #3 P112_SOD1_scene-08_roi1 158.99093 1104.3551 940.9151
  #4 P112_SOD1_scene-14_roi1 180.61249  781.3340 747.0570
  #5   P112_WT_scene-13_roi1  15.22344 1034.8931 709.8290
  </code></pre>
  <p>My idea was to first merge both dataframes based on <code>Image</code> so that the angle and origin would be duplicated for each row (this works well), and then apply the <code>rearrr::rotate_2d</code> function to each row. This is when I run into trouble because it wants the same angle and origin for all rows.</p>
  <pre><code># Merge rotation info into data
  data &lt;- merge(data, rotation_info, by=&quot;Image&quot;, all.x=TRUE)
  
  # Rotate based on angle (&quot;Angle&quot;) and origin (&quot;CC_X&quot;, &quot;CC_Y&quot;)
  data &lt;- rotate_2d(data, degrees = data$Angle, x_col = &quot;CenterX_um&quot;, y_col = &quot;CenterY_um&quot;,
                    origin = c(data$CC_X, data$CC_Y) , suffix = &quot;&quot;, overwrite = TRUE)
  </code></pre>
  <p>Any other approach is welcome. I don't necessarily need the rotation info in my dataframe (I was planning to drop it after, actually).</p>
  <p>Thanks in advance!</p>