<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def radviz(self, column_names, transforms=dict(), **kwargs):
 """ Radviz plot. Useful for exploratory visualization, a radviz plot can show multivariate data in 2D. Conceptually, the variables (here, specified in `column_names`) are distributed evenly around the unit circle. Then each point (here, each row in the dataframe) is attached to each variable by a spring, where the stiffness of the spring is proportional to the value of corresponding variable. The final position of a point represents the equilibrium position with all springs pulling on it. In practice, each variable is normalized to 0-1 (by subtracting the mean and dividing by the range). This is a very exploratory plot. The order of `column_names` will affect the results, so it's best to try a couple different orderings. For other caveats, see [1]. Additional kwargs are passed to self.scatter, so subsetting, callbacks, and other configuration can be performed using options for that method (e.g., `genes_to_highlight` is particularly useful). Parameters column_names : list Which columns of the dataframe to consider. The columns provided should only include numeric data, and they should not contain any NaN, inf, or -inf values. transforms : dict Dictionary mapping column names to transformations that will be applied just for the radviz plot. For example, np.log1p is a useful function. If a column name is not in this dictionary, it will be used as-is. ax : matplotlib.Axes If not None, then plot the radviz on this axes. If None, then a new figure will be created. kwargs : dict Additional arguments are passed to self.scatter. Note that not all possible kwargs for self.scatter are necessarily useful for a radviz plot (for example, margninal histograms would not be meaningful). Notes ----- This method adds two new variables to self.data: "radviz_x" and "radviz_y". It then calls the self.scatter method, using these new variables. The data transformation was adapted from the pandas.tools.plotting.radviz function. References [1] Hoffman,P.E. et al. (1997) DNA visual and analytic data mining. In the Proceedings of the IEEE Visualization. Phoenix, AZ, pp. 437-441. [2] http://www.agocg.ac.uk/reports/visual/casestud/brunsdon/radviz.htm [3] http://pandas.pydata.org/pandas-docs/stable/visualization.html\ #radviz """

        # make a copy of data
        x = self.data[column_names].copy()

        for k, v in transforms.items():
            x[k] = v(x[k])

        def normalize(series):
            mn = min(series)
            mx = max(series)
            return (series - mn) / (mx - mn)

        df = x.apply(normalize)

        to_plot = []

        n = len(column_names)

        s = np.array([(np.cos(t), np.sin(t))
                      for t in [2.0 * np.pi * (i / float(n))
                                for i in range(n)]])

        for i in range(len(x)):
            row = df.irow(i).values
            row_ = np.repeat(np.expand_dims(row, axis=1), 2, axis=1)
            to_plot.append((s * row_).sum(axis=0) / row.sum())

        x_, y_ = zip(*to_plot)
        self.data['radviz_x'] = x_
        self.data['radviz_y'] = y_

        ax = self.scatter('radviz_x', 'radviz_y', **kwargs)

        ax.add_patch(patches.Circle((0.0, 0.0), radius=1.0, facecolor='none'))
        for xy, name in zip(s, column_names):
            ax.add_patch(patches.Circle(xy, radius=0.025, facecolor='gray'))
            if xy[0] < 0.0 and xy[1] < 0.0:
                ax.text(xy[0] - 0.025, xy[1] - 0.025, name,
                        ha='right', va='top', size='small')
            elif xy[0] < 0.0 and xy[1] >= 0.0:
                ax.text(xy[0] - 0.025, xy[1] + 0.025, name,
                        ha='right', va='bottom', size='small')
            elif xy[0] >= 0.0 and xy[1] < 0.0:
                ax.text(xy[0] + 0.025, xy[1] - 0.025, name,
                        ha='left', va='top', size='small')
            elif xy[0] >= 0.0 and xy[1] >= 0.0:
                ax.text(xy[0] + 0.025, xy[1] + 0.025, name,
                        ha='left', va='bottom', size='small')

        ax.axis('equal')
        return ax