如何将具有不同 0 值的字符串转换为 1 到 4 范围内的单个值(n° 值不为零)

How to convert a string with different 0 values, in a single value ranging from 1 to 4 (n° of values different from zero)

我有以下 table:

并且对于每个单元格,我想获得不同于 0 的值的 n°。

以前两行为例:

denovoLocus10   9   C   0   1   0

denovoLocus12   7   G   3   3   4

这是我在 R 中的做法。

#load package
library(tidyverse)

#here is the data you gave us
test_data <- tibble(Tag = paste0("denovoLocus", c(10, 12, 14, 16, 17)),
       Locus = c(9,7,37,5,4),
       ref = c("C", "G", "C", "T", "C"),
       RA02_R1_2 = c("0/0/0/0", "22/0/262/1", "0/0/0/0", "0/0/0/0", "0/7/0/0"),
       RA03_R1_2 = c("0/223/0/0", "22/0/989/15", "0/5/0/0", "0/0/0/0", "0/42/0/0"),
       RA06_R1_2 = c("0/0/0/0", "25/3/791/3", "0/4/0/0", "0/0/0/8", "0/31/0/3"))

#split and count the elements that do not equal zero and them collapse them
test_data%>%
  mutate(across(RA02_R1_2:RA06_R1_2, ~map_dbl(., ~str_split(.x, pattern = "/") %>%
                                            map_dbl(., ~sum(.x != "0") )))) %>%
  unite(col = "final", everything(), sep = " ")
#> # A tibble: 5 x 1
#>   final                   
#>   <chr>                   
#> 1 denovoLocus10 9 C 0 1 0 
#> 2 denovoLocus12 7 G 3 3 4 
#> 3 denovoLocus14 37 C 0 1 1
#> 4 denovoLocus16 5 T 0 0 1 
#> 5 denovoLocus17 4 C 1 1 2

首先使用 across 我用一堆“/”总结了列。我首先使用 str_split 通过“/”拆分元素,然后计算不等于零的元素 (sum(.x != "0"))。这有点复杂,因为拆分会产生一个列表,因此您需要 map 遍历列表以提取值。最后,我们使用 unite 将所有列折叠成您想要的字符串格式。

创建一个简单的测试数据框后,因为数据本身在屏幕截图中而不是可复制的东西中:

df = pd.DataFrame({'A': ['0/0/0/0', '0/245/42/0']})

只需使用正则表达式将所有整数提取为字符串,将所有字符串 '0' 替换为 np.nan。然后在每个原始索引级别组内计数(注意 count 自动排除 NaN):

>>> df['A_count'] = df['A'].str.extractall(r'(\d+)').replace('0', np.nan) \
...     .groupby(level=0).count()
>>> df
            A  A_count
0     0/0/0/0        0
1  0/245/42/0        2

如果您希望它对多列执行此操作,请过滤您的列并使用 for 循环遍历它们。 (这也可以通过在这些列上添加 apply 来完成。)例如:

for c in df.filter(regex=r'RA\d{2}_R1_2'):
    df[c + '_count'] = df[c].str.extractall(r'(\d+)').replace('0', np.nan) \
        .groupby(level=0).count()