<p>If the numbers are in quotes it means that it has read them as text. A numeric vector will be:</p>
<p>[1] 2 0 1 1 1 1 1</p>
<p>To replace that column with the new value you can use this:</p>
<pre><code>het_df[,3] &lt;- sapply(as.numeric(het_df[,3]), FUN=function(x){-1*(x-1)})
</code></pre>
<p>I used <code>het_df[, 3] &lt;- </code> to replace the content of the column.
I changed <code>lapply</code> to <code>sapply</code>, to get a vector and not a list.
I forced the input to be numeric via <code>as.numeric</code>.<br />
The syntax of the functions was wrong, to create a function in R you need <code>function(x){#code}</code>. The linked question is for a function that has an argument called formula, which is not the case here, because you want to define your own (anonymous) function.</p>

CC BY-SA 4.0
2023-01-04T16:16:39.943Z
Thank you so much that's exactly what I needed! That makes a lot more sense too - thank you for explaining what was going on. 

If you wouldn't mind can I ask you one more question? How would you work a rolling window into this data? From my above python code I was able to complete it using a for loop and the pandas package. Everywhere I am looking to try and replicate it in R is telling me a lot of different things so if you know a good place to look or if you have any advice moving forward that would be great!
rimo
CC BY-SA 4.0
2023-01-05T20:03:58.617Z
That's a different question entirely; please try to limit posts to one question only, and [ask a new question](https://bioinformatics.stackexchange.com/questions/ask) if you have follow-ups.
gringer
CC BY-SA 4.0
2023-01-04T09:58:49.233Z
2023-01-04T09:58:49.233Z
llrs
<p>Doing mathematical operations on a matrix will only work if <em>all</em> the matrix elements are numerical. In your case, you have mixed character and numerical variables, and it looks like a data frame or tibble would be more appropriate (calling it <code>het_df</code> is a strong indicator that this is actually what you want to do, as well as the <code>pandas</code> structures in the python code). You can load a TSV file into a tibble in R using the <code>read_tsv</code> function from <code>tidyverse</code>:</p>
<pre><code>library(tidyverse);
het_df &lt;- read_tsv(&quot;input_file_name.tsv&quot;);
</code></pre>
<p>After this, numerical mathematical operations can be carried out column-by-column, because the columns are treated as separate structures internally:</p>
<pre><code>het_df$het &lt;- -1 * (het_df$het - 1); # approach 1 [base R]
het_df &lt;- mutate(het_df, het = -1 * (het - 1); # approach 2 [tidyverse]
</code></pre>

CC BY-SA 4.0
2023-01-05T20:02:45.980Z
2023-01-05T20:02:45.980Z
gringer
<p>I have a matrix that looks something like this:</p>
<div class="s-table-container">
<table class="s-table">
<thead>
<tr>
<th>chr</th>
<th>pos</th>
<th>het</th>
</tr>
</thead>
<tbody>
<tr>
<td>chrI</td>
<td>27</td>
<td>2</td>
</tr>
<tr>
<td>chrI</td>
<td>55</td>
<td>0</td>
</tr>
<tr>
<td>chrI</td>
<td>27</td>
<td>0</td>
</tr>
<tr>
<td>chrI</td>
<td>55</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
<p>It's essentially a VCF file that I have converted into a TSV. I want to be able to take all the values in the <code>het</code> column and apply this function:
<code>het_df['het'] = het_df['het'].transform(lambda x: -1*(x-1))</code></p>
<p>That line is from a python script and it works really well in transforming that column. However, as I am making plots from this data I want to be able to do this in R. When I went to convert it to an R script I started with this function:</p>
<p><code>convert_df &lt;- lapply(het_df[,3], FUN=function(x) formula=(-1*(x-1)))</code></p>
<p>As I saw it in this issue: <a href="https://stackoverflow.com/questions/7009333/how-to-use-lapply-with-a-formula">https://stackoverflow.com/questions/7009333/how-to-use-lapply-with-a-formula</a></p>
<p>However, I keep getting error messages such as this one:</p>
<pre><code>Error in x - 1 : non-numeric argument to binary operator
</code></pre>
<p>Which is odd because when I run <code>het_df[,3]</code> it gives me the correct output:</p>
<pre><code>   [1] &quot;2&quot; &quot;0&quot; &quot;1&quot; &quot;1&quot; &quot;1&quot; &quot;1&quot; &quot;1&quot;
</code></pre>
<p>I think I'm just a little lost and I don't know what to do to run this function...everything worked fine in my python script (I was able to generate plots with matplotlib) but I like manipulating plots more in R than python so I wanted to be able to convert the script. If anyone is able to see what I'm clearly doing wrong please let me know! Thank you!</p>
<p>Here is the python code I've been using in case this helps (I'm transforming the last column so I always get a 1 or a 0 for heterozygosity/homosygosity and then using a rolling window to obtain the variability in the data series and plotting them):</p>
<pre><code>import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

# read in file
het_df = pd.read_csv(&quot;het_file.tsv&quot;, sep=&quot;\t&quot;, header=None).set_axis(['chr', 'pos', 'het'], axis=1, copy=False)

# getting rid of homozygous alt allele
# always get 1 for heterozygosity
het_df['het'] = het_df['het'].transform(lambda x: -1*(x-1))

windows = [25, 50, 100, 200] # 100 bp, get rid of a lot of noise
steps = [5]

for window in windows:
    for step in steps:
        het_ratio = {}
        for chr_het_df in het_df.groupby('chr'):
            # rolling over the window
            # center = have the count in the center of the window
            # 50bp window count in the front or back of window or count in the center
            # ratio of heterozygosity
            het_ratio[chr_het_df[0]] = chr_het_df[1].set_index('pos').rolling(window=window, step=step, center=True).mean()
        fig, ax = plt.subplots(len(het_ratio), 1, sharex=True)
        for index in range(len(het_ratio)):
            chromosome = list(het_ratio.keys())[index] 
            sns.scatterplot(het_ratio[chromosome], ax=ax[index], s=4)
            ax[index].set_ylim(bottom=0, top=1)
            ax[index].legend([], [], frameon=False)
            ax[index].set(xlabel=&quot;Chromosome position&quot;, ylabel=chromosome)
            ax[index].set_yticks([0, 0.5, 1])
            ax[index].set_yticklabels([0, 0.5, 1], size = 6)
        fig.subplots_adjust(top=0.98, bottom=0.05, left=0.05, right=0.98)
        fig.set_size_inches(20, 15)
        plt.savefig(&quot;het_plot&quot; + str(window) + &quot;_step&quot; + str(step) + &quot;.png&quot;, dpi=150)
<span class="math-container">```</span>
</code></pre>

<r><python>
How to apply a mathematical function to a matrix in R
# How to apply a mathematical function to a matrix in R

(Asked by: username_0 on 2023-01-03)

I have a matrix that looks something like this:




chr
pos
het




chrI
27
2


chrI
55
0


chrI
27
0


chrI
55
1




It's essentially a VCF file that I have converted into a TSV. I want to be able to take all the values in the het column and apply this function:
het_df['het'] = het_df['het'].transform(lambda x: -1*(x-1))
That line is from a python script and it works really well in transforming that column. However, as I am making plots from this data I want to be able to do this in R. When I went to convert it to an R script I started with this function:
convert_df <- lapply(het_df[,3], FUN=function(x) formula=(-1*(x-1)))
As I saw it in this issue: https://stackoverflow.com/questions/7009333/how-to-use-lapply-with-a-formula
However, I keep getting error messages such as this one:
Error in x - 1 : non-numeric argument to binary operator

Which is odd because when I run het_df[,3] it gives me the correct output:
   [1] "2" "0" "1" "1" "1" "1" "1"

I think I'm just a little lost and I don't know what to do to run this function...everything worked fine in my python script (I was able to generate plots with matplotlib) but I like manipulating plots more in R than python so I wanted to be able to convert the script. If anyone is able to see what I'm clearly doing wrong please let me know! Thank you!
Here is the python code I've been using in case this helps (I'm transforming the last column so I always get a 1 or a 0 for heterozygosity/homosygosity and then using a rolling window to obtain the variability in the data series and plotting them):
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

# read in file
het_df = pd.read_csv("het_file.tsv", sep="\t", header=None).set_axis(['chr', 'pos', 'het'], axis=1, copy=False)

# getting rid of homozygous alt allele
# always get 1 for heterozygosity
het_df['het'] = het_df['het'].transform(lambda x: -1*(x-1))

windows = [25, 50, 100, 200] # 100 bp, get rid of a lot of noise
steps = [5]

for window in windows:
    for step in steps:
        het_ratio = {}
        for chr_het_df in het_df.groupby('chr'):
            # rolling over the window
            # center = have the count in the center of the window
            # 50bp window count in the front or back of window or count in the center
            # ratio of heterozygosity
            het_ratio[chr_het_df[0]] = chr_het_df[1].set_index('pos').rolling(window=window, step=step, center=True).mean()
        fig, ax = plt.subplots(len(het_ratio), 1, sharex=True)
        for index in range(len(het_ratio)):
            chromosome = list(het_ratio.keys())[index] 
            sns.scatterplot(het_ratio[chromosome], ax=ax[index], s=4)
            ax[index].set_ylim(bottom=0, top=1)
            ax[index].legend([], [], frameon=False)
            ax[index].set(xlabel="Chromosome position", ylabel=chromosome)
            ax[index].set_yticks([0, 0.5, 1])
            ax[index].set_yticklabels([0, 0.5, 1], size = 6)
        fig.subplots_adjust(top=0.98, bottom=0.05, left=0.05, right=0.98)
        fig.set_size_inches(20, 15)
        plt.savefig("het_plot" + str(window) + "_step" + str(step) + ".png", dpi=150)
```

**Tags:** r, python

---

## 2 answers

### Answer by username_1 on 2023-01-04. Score: 1

If the numbers are in quotes it means that it has read them as text. A numeric vector will be:
[1] 2 0 1 1 1 1 1
To replace that column with the new value you can use this:
het_df[,3] <- sapply(as.numeric(het_df[,3]), FUN=function(x){-1*(x-1)})

I used het_df[, 3] <-  to replace the content of the column.
I changed lapply to sapply, to get a vector and not a list.
I forced the input to be numeric via as.numeric.
The syntax of the functions was wrong, to create a function in R you need function(x){#code}. The linked question is for a function that has an argument called formula, which is not the case here, because you want to define your own (anonymous) function.

> **Comments:**
> **username_0**: Thank you so much that's exactly what I needed! That makes a lot more sense too - thank you for explaining what was going on.   If you wouldn't mind can I ask you one more question? How would you work a rolling window into this data? From my above python code I was able to complete it using a for loop and the pandas package. Everywhere I am looking to try and replicate it in R is telling me a lot of different things so if you know a good place to look or if you have any advice moving forward that would be great!  
> **username_2**: That's a different question entirely; please try to limit posts to one question only, and [ask a new question](https://bioinformatics.stackexchange.com/questions/ask) if you have follow-ups.  

---

### Answer by username_2 on 2023-01-05. Score: 0

Doing mathematical operations on a matrix will only work if all the matrix elements are numerical. In your case, you have mixed character and numerical variables, and it looks like a data frame or tibble would be more appropriate (calling it het_df is a strong indicator that this is actually what you want to do, as well as the pandas structures in the python code). You can load a TSV file into a tibble in R using the read_tsv function from tidyverse:
library(tidyverse);
het_df <- read_tsv("input_file_name.tsv");

After this, numerical mathematical operations can be carried out column-by-column, because the columns are treated as separate structures internally:
het_df$het <- -1 * (het_df$het - 1); # approach 1 [base R]
het_df <- mutate(het_df, het = -1 * (het - 1); # approach 2 [tidyverse]


---

