如何将具有不同 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()
我有以下 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()