【问题标题】:Using dplyr in order to change column value according to another df使用 dplyr 以根据另一个 df 更改列值
【发布时间】:2020-10-08 12:34:13
【问题描述】:

您好,我有一个 df1

scaf_name       coordinates value    
JZSA01000001.1  1   2
JZSA01000001.1  2   2
JZSA01000001.1  3   2
JZSA01000001.1  4   2
JZSA01000001.1  5   2
JZSA01000001.1  6   2
JZSA01000001.1  7   2
JZSA01000001.1  8   2
JZSA01000001.1  9   2
JZSA01000001.1  10  2
JZSA01000001.1  11  5
JZSA01000001.1  12  5
JZSA01000001.1  13  5
JZSA01000001.1  14  5
JZSA01000001.1  15  5
JZSA01000001.1  16  5
JZSA01000001.1  17  5
JZSA01000001.1  18  6
JZSA01000002.1  1   2
JZSA01000002.1  2   2
JZSA01000002.1  3   2
JZSA01000002.1  4   2
JZSA01000002.1  5   2
JZSA01000002.1  6   2
JZSA01000003.1  1   5
JZSA01000003.1  2   5
JZSA01000003.1  3   6
JZSA01000003.1  4   6
JZSA01000003.1  5   6
JZSA01000003.1  6   6
JZSA01000003.1  7   6
JZSA01000003.1  8   6
JZSA01000003.1  9   6

还有另一个df_interval

scaffold          start     end
JZSA01000001.1_0  1         14
JZSA01000001.1_1  15        18
JZSA01000002.1    1         12
JZSA01000003.1_0  1         3
JZSA01000003.1_1  4         6
JZSA01000003.1_2  7         9

我想根据df1$scaf_name$startdf1$scaf_name$end更改df1$scaf_name

比如

每个包含df_interval$scaffolddf1$scaf_name 以及df1$coordinates os 之间的1-14 将被命名为JZSA01000001.1_0

这里我应该得到输出

scaf_name       coordinates value    
JZSA01000001.1_0    1   2
JZSA01000001.1_0    2   2
JZSA01000001.1_0    3   2
JZSA01000001.1_0    4   2
JZSA01000001.1_0    5   2
JZSA01000001.1_0    6   2
JZSA01000001.1_0    7   2
JZSA01000001.1_0    8   2
JZSA01000001.1_0    9   2
JZSA01000001.1_0    10  2
JZSA01000001.1_0    11  5
JZSA01000001.1_0    12  5
JZSA01000001.1_0    13  5
JZSA01000001.1_0    14  5
JZSA01000001.1_1    15  5
JZSA01000001.1_1    16  5
JZSA01000001.1_1    17  5
JZSA01000001.1_1    18  6
JZSA01000002.1      1   2
JZSA01000002.1      2   2
JZSA01000002.1      3   2
JZSA01000002.1      4   2
JZSA01000002.1      5   2
JZSA01000002.1      6   2
JZSA01000003.1_0    1   5
JZSA01000003.1_0    2   5
JZSA01000003.1_0    3   6
JZSA01000003.1_1    4   6
JZSA01000003.1_1    5   6
JZSA01000003.1_1    6   6
JZSA01000003.1_2    7   6
JZSA01000003.1_2    8   6
JZSA01000003.1_2    9   6

df1 文件非常大,如果有人想尽可能快,那就太棒了。 谢谢

数据

df1

structure(list(scaf_name = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("JZSA01000001.1", 
"JZSA01000002.1", "JZSA01000003.1"), class = "factor"), coor = c(1L, 
2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 
16L, 17L, 18L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 
7L, 8L, 9L), dinates.value = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 2L, 2L, 2L, 2L, 2L, 2L, 
5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L)), class = "data.frame", row.names = c(NA, 
-33L))

df_interval

structure(list(scaffold = structure(1:6, .Label = c("JZSA01000001.1_0", 
"JZSA01000001.1_1", "JZSA01000002.1", "JZSA01000003.1_0", "JZSA01000003.1_1", 
"JZSA01000003.1_2"), class = "factor"), start = c(1L, 15L, 1L, 
1L, 4L, 7L), end = c(14L, 18L, 12L, 3L, 6L, 9L)), class = "data.frame", row.names = c(NA, 
-6L))

我得到了这个解决方案:

library(data.table)
setDT(df1)[df_interval, scaf_name := scaffold,
         on =  .(coordinates >= start, coordinates <= end)]

但对于某些scaf_name,它们会从输出中删除...


为 Ronak 编辑

这里是等价的头(df_interval,这里叫interval_tab之后)我用的代码

setDT(interval_tab)[, scaf_name := sub("(?

> head(interval_tab)
       scaffold start   end  scaf_name
1:   KQ759765.1     1  1417 KQ759765.1
2:   KQ759766.1     1  1389 KQ759766.1
3: KQ759767.1_0     1 23930 KQ759767.1
4: KQ759767.1_1 23931 83220 KQ759767.1
5: KQ759767.1_2 83221 92117 KQ759767.1
6: KQ759767.1_3 92118 92679 KQ759767.1

这里是等效df1的头部(这里称为tab

> head(tab)
           V1 V2 V3
1: KQ759765.1  1  0
2: KQ759765.1  2  0
3: KQ759765.1  3  0
4: KQ759765.1  4  0
5: KQ759765.1  5  0
6: KQ759765.1  6  0

然后我使用了你的代码:

> setDT(tab)[interval_tab, scaf_name := scaffold,on =  .(scaf_name, V2 >= start, V2 <= end)]

并收到错误消息

Error in colnamesInt(x, names(on), check_dups = FALSE) : 
  argument specifying columns specify non existing column(s): cols[1]='scaf_name'

【问题讨论】:

  • 您能否指定“每个包含 df_interval$scaffold 的 df1$scaf_name 以及 1-14 之间的 df1$coordinates os 将被命名为 JZSA01000001.1_0”?你的意思是当每个没有下划线之前的脚手架都与 scaf_name 匹配?

标签: r dataframe dplyr data.table


【解决方案1】:

您需要创建一个在df_intervaldf1 之间通用的密钥。为此,您可以创建一个新列以删除 scaffold 列中下划线后的所有内容,然后进行连接。

library(data.table)
setDT(df_interval)[, scaf_name := sub('_.*', '', scaffold)]

setDT(df1)[df_interval, scaf_name := scaffold,on =  
                       .(scaf_name, coor >= start, coor <= end)]

这会返回:

#           scaf_name coor dinates.value
# 1: JZSA01000001.1_0    1             2
# 2: JZSA01000001.1_0    2             2
# 3: JZSA01000001.1_0    3             2
# 4: JZSA01000001.1_0    4             2
# 5: JZSA01000001.1_0    5             2
# 6: JZSA01000001.1_0    6             2
# 7: JZSA01000001.1_0    7             2
# 8: JZSA01000001.1_0    8             2
# 9: JZSA01000001.1_0    9             2
#10: JZSA01000001.1_0   10             2
#11: JZSA01000001.1_0   11             5
#12: JZSA01000001.1_0   12             5
#13: JZSA01000001.1_0   13             5
#14: JZSA01000001.1_0   14             5
#15: JZSA01000001.1_1   15             5
#16: JZSA01000001.1_1   16             5
#17: JZSA01000001.1_1   17             5
#18: JZSA01000001.1_1   18             6
#19:   JZSA01000002.1    1             2
#20:   JZSA01000002.1    2             2
#21:   JZSA01000002.1    3             2
#22:   JZSA01000002.1    4             2
#23:   JZSA01000002.1    5             2
#24:   JZSA01000002.1    6             2
#25: JZSA01000003.1_0    1             5
#26: JZSA01000003.1_0    2             5
#27: JZSA01000003.1_0    3             6
#28: JZSA01000003.1_1    4             6
#29: JZSA01000003.1_1    5             6
#30: JZSA01000003.1_1    6             6
#31: JZSA01000003.1_2    7             6
#32: JZSA01000003.1_2    8             6
#33: JZSA01000003.1_2    9             6
#           scaf_name coor dinates.value

【讨论】:

  • 您好,谢谢您,我试过了,但我收到了消息:``` colnamesInt 中的错误(i,unname(on),check_dups = FALSE):指定列的参数指定不存在的列: cols[1]='scaf_name' ```你有想法@Ronak 吗?
  • 您是在您共享的数据或其他一些数据上进行测试吗?正则表达式可能在不同的数据上有所不同。这里的关键是df1df_interval 中的列名应该匹配。
  • 是的,我现在在其他更大的数据上使用它,它们应该匹配你的意思是所有值都应该匹配?
  • 注意你的第一个df1 值,它是JZSA01000001.1,现在检查你的第一个df_interval 值它是JZSA01000001.1_0。我们需要匹配它们,但我们不能直接这样做。在我的回答中,我在第一行setDT(df_interval)[, scaf_name := sub('_.*', '', scaffold)] 中使用sub 删除下划线后的所有内容,以便JZSA01000001.1_0 变为JZSA01000001.1,这将匹配df1 中的值。你现在需要在你的真实数据集中做同样的事情,这样列值是相同的,我们可以加入它们。
  • 您在tab 中没有scaf_name,因此您必须提及您要加入的列。试试setDT(tab)[interval_tab, scaf_name := scaffold,on = .(V1 = scaf_name, V2 &gt;= start, V2 &lt;= end)]
【解决方案2】:

这可行,您只需删除旧列即可:

library(dplyr)
df1 = structure(list(scaf_name = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 
                                             1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
                                             2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("JZSA01000001.1", 
                                                                                                     "JZSA01000002.1", "JZSA01000003.1"), class = "factor"), coor = c(1L, 
                                                                                                                                                                      2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 
                                                                                                                                                                      16L, 17L, 18L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 
                                                                                                                                                                      7L, 8L, 9L), dinates.value = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
                                                                                                                                                                                                     2L, 2L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 2L, 2L, 2L, 2L, 2L, 2L, 
                                                                                                                                                                                                     5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L)), class = "data.frame", row.names = c(NA, 
                                                                                                                                                                                                                                                                               -33L))
df_interval = structure(list(scaffold = structure(1:6, .Label = c("JZSA01000001.1_0", 
                                                                  "JZSA01000001.1_1", "JZSA01000002.1", "JZSA01000003.1_0", "JZSA01000003.1_1", 
                                                                  "JZSA01000003.1_2"), class = "factor"), start = c(1L, 15L, 1L, 
                                                                                                                    1L, 4L, 7L), end = c(14L, 18L, 12L, 3L, 6L, 9L)), class = "data.frame", row.names = c(NA, 
                                                                                                                                                                                                          -6L))
df_t = df1 %>%
  inner_join(df_interval, by = c("scaf_name" = "scaffold")) %>%
  mutate(newcol = case_when(coor>= 1 & coor <= 14 ~ "JZSA01000001.1_0 ")) %>%
  select(c("newcol", "coor", "dinates.value"))

编辑 现在旧值 a 已被替换。我从inner join变成了left join

df_t = df1 %>%
  left_join(df_interval, by = c("scaf_name" = "scaffold")) %>%
  mutate(scaf_name = replace(scaf_name, coor >= 1 &
                               coor <= 14 &
                               !is.na(end), "JZSA01000001.1_0")) %>% 
  select(c("scaf_name", "coor", "dinates.value"))

编辑 2

好的,现在我想我明白了。假设下划线拆分没问题,这很有效,看起来像您的解决方案:

df_interval$shorti = do.call(rbind, strsplit(as.character(df_interval$scaffold), "_"))[,1]
df_t = df1 %>%
  left_join(df_interval, by = c("scaf_name" = "shorti")) %>%
  filter(coor >= start & coor <= end) %>%
  mutate(scaf_name = ifelse(coor >= start &
                              coor <= end, as.character(scaffold), scaf_name)) %>%
  select(c("scaf_name", "coor", "dinates.value"))

【讨论】:

  • 你好,谢谢,但我不明白你为什么要添加这部分:case_when(coor&gt;= 1 &amp; coor &lt;= 14 ~ "JZSA01000001.1_0 "))结果只给我JZSA01000001.1then 的输出,而不是所有序列的输出...... @sequoia跨度>
  • 不太准确,JZSA01000002.1已被删除我不知道为什么,也许你可以看到我在帖子中写的预期输出?
  • 你好,我使用了另一个数据框并得到了错误:Error in vec_slice(x_out, x_slicer) : long vectors not supported yet: ../../src/include/Rinlinedfuns.h:519你知道发生了什么吗? @红杉
  • 它不再重要了吗?由于您将其他答案标记为有帮助。但这只是意味着您的矩阵/向量太大。以及这里的建议(stackoverflow.com/q/60419930/6946122),您可以使用biglm
猜你喜欢
  • 2022-06-10
  • 2020-08-07
  • 1970-01-01
  • 2019-11-02
  • 2016-09-19
  • 2022-12-03
  • 1970-01-01
  • 2012-10-15
  • 2020-12-29
相关资源
最近更新 更多