The Yun's SD card is attached to, and managed by, the Linux system. The I2C pins on the header connector are only connected to the AVR processor, and can only be controlled by a sketch. Something needs to get the data from the sketch to the SD card.
When you use FileIO to write to a file, you are using the Bridge library to send data over the serial port that is between the two systems. This data includes information about the file to be opened, as well as the data for the file. As you have found, it is a rather inefficient way to write to the SD card.
File operations performed directly by code on the Linux processor are much faster. But you still need to get the data from the sketch to the Linux processor so that code can write the data. The way I normally do that is through the Process class.
I write a Python script (you can use any language you prefer) that reads data from standard input, processes and formats it as necessary, and writes it to the SD card. The sketch uses the Process class to start the Python script, and then in the loop() function it reads the external data and writes it to the process object. The Python script receives that data, and writes it to the file.
Since the Linux processor is so much faster and more powerful than the sketch processor, I do the minimum amount of processing in the sketch, and try to do as much as possible on the Linux side. But I temper that with the amount of data, and do only as much as processing on the sketch side as necessary to minimize the amount of data that goes over the bridge. For example, in one of my projects, I want to get an average reading of a quickly varying waveform. So instead of sending a lot of data down to the Linux side, my sketch quickly reads and totals 1000 raw analog samples, and then sends that one total value down to the Linux side. The Linux side then divides by the number of samples, scales the raw reading to the proper engineering units and then stores the data. In this way, there is no need to send all of the samples down to the Linux side, but also the sketch doesn't have to do the floating point math to scale the data, and it certainly doesn't have to scale each individual sample.
So it can be a delicate balance of how much processing you want to do on each side. The I2C data collection must happen in the sketch. The file writing operations should happen on the Linux side. To determine where the rest of the processing should be, you need to analyze your data and the required processing and identify the minimum amount of processing needed to generate the minimum amount of data. That processing should happen in the sketch, the data gets passed to the Linux side using the process object, and the rest of the processing and the file writing happens on the Linux side.
If there is data going the other way as well, that can also be handled by the same process connection: anything that the Linux side code writes to standard output can be read by the sketch and used to control outputs. In the example I mentioned above, I am controlling some low voltage AC lighting. A current transformer is used to measure the lighting current, and the values are read and averaged by the sketch and sent to the Linux side, while the Linux side sends on/off commands up to the sketch which is used to control a power relay to control the lights. Most of the processing and all of the control decisions happen on the Linux side, while the sketch is a slightly intelligent I/O processor.
Using the Process class to communicate with the Linux side and doing the file access in Linux should significantly speed things up. Minimizing the amount of data sent to the Linux side will help. While the Process communications are more efficient than FileIO, you may still have trouble with the high data rates that you desire.