R 数据帧内值的条件分割

R 数据帧内值的条件分割,r,if-statement,conditional-statements,division,R,If Statement,Conditional Statements,Division,首先让我感叹一下,我对R相当陌生,对于一个有经验的用户来说,这可能很容易。 我一直在试图弄清楚如何在一个数据帧内执行有条件的值分割。具体地说,我有一个带有多个标识符的数据帧(如下面的df1)。我想用向量中的值或df(df2)中匹配的唯一标识符(如下所示)来划分这些值,同时保持标识符的完整性 ID = c("nr6536","nr8798","nr8723","nr8276","nr7774","nr0093") Conc = c("1:2","1:4","1:2","1:8","1:4","1:

首先让我感叹一下,我对R相当陌生,对于一个有经验的用户来说,这可能很容易。 我一直在试图弄清楚如何在一个数据帧内执行有条件的值分割。具体地说,我有一个带有多个标识符的数据帧(如下面的
df1
)。我想用向量中的值或df(
df2
)中匹配的唯一标识符(如下所示)来划分这些值,同时保持标识符的完整性

ID = c("nr6536","nr8798","nr8723","nr8276","nr7774","nr0093")
Conc = c("1:2","1:4","1:2","1:8","1:4","1:4")
ID1 = c("ID","Conc","Eb","Eb","Sd","Sd","Re","Sd")
ID2 = c("Re","Sd","Eb")
dat1 = c(2,3,4,5,6,7)
dat2 = c(8,9,10,11,12,13)
dat3 = c(1,2,3,4,5,6)
dat4 = c(4,3,2,7,6,5)
dat5 = c(8,7,6,3,4,8)
dat6 = c(6,4,2,5,3,8)
dat7 = c(9,2,7)

df1 = data.frame(ID,Conc,dat1,dat2,dat3,dat4,dat5,dat6)
colnames(df1)=ID1
df2 = data.frame(t(dat7)); colnames(df2)=ID2
rm(ID,Conc,ID1,ID2,dat1, dat2,dat3,dat4,dat5,dat6,dat7)
想要的输出:

    ID      Conc  Eb      Eb      Sd   Sd   Re     Sd
    nr6536  1:2   0.2857  1.1429  0.5  2    0.8889 3
    nr8798  1:4   0.4286  1.2857  1    1.5  0.7778 2
    nr8723  1:2   0.5714  1.4286  1.5  1    0.6667 1
    nr8276  1:8   0.7143  1.5714  2    3.5  0.3333 2.5
    nr7774  1:4   0.8571  1.7143  2.5  3    0.4444 1.5
    nr0093  1:4   1       1.8571  3    2.5  0.8889 4
我尝试了
ave
tablate
ifelse
,但未能获得所需的输出。下面给出了一个非功能性示例:

library(reshape2)
df1.2 = melt(df1)
df2names = colnames(df2)
df2.2 = as.data.frame(t(df2)); df2.2$variable=df2names

df3 = as.data.frame(apply(df1.2,1,function(x){
                    ScaVal = ifelse(x$variable %in% df2.2$variable, value/df2.2$V1)
                    return(ScaVal)
}))

有人对如何做到这一点有什么建议吗?提前谢谢你

我通常更喜欢
tidyverse
解决方案,但由于
df1
中没有唯一的变量名,因此会遇到问题。相反,使用
for loop
(我知道这很令人震惊!)的基本R解决方案。但是,除非您的数据帧中有数百万列,否则我认为您的性能不会有任何问题

conditional_divide <- function(df1, df2) {
    for (i in seq_len(ncol(df1))) {
        if (colnames(df1)[i] %in% colnames(df2)) {
            df1[,i] <- df1[,i] / df2[[colnames(df1)[i]]]
        }
    }
    return(df1)
}

conditional_divide (df1, df2)

      ID Conc        Eb       Eb  Sd  Sd        Re  Sd
1 nr6536  1:2 0.2857143 1.142857 0.5 2.0 0.8888889 3.0
2 nr8798  1:4 0.4285714 1.285714 1.0 1.5 0.7777778 2.0
3 nr8723  1:2 0.5714286 1.428571 1.5 1.0 0.6666667 1.0
4 nr8276  1:8 0.7142857 1.571429 2.0 3.5 0.3333333 2.5
5 nr7774  1:4 0.8571429 1.714286 2.5 3.0 0.4444444 1.5
6 nr0093  1:4 1.0000000 1.857143 3.0 2.5 0.8888889 4.0

conditional\u divide这里有一种方法可以使用(部分
tidyverse
)来完成此操作。
注意:它确实涉及允许
df1
采用唯一的列名

library(tidyverse)

df1 <- df1 %>% setNames(make.names(names(.), unique = TRUE))
values <- df2 %>% unlist(.)

update <- function(df, val, name) mutate_at(df, vars(starts_with(name)), funs(./val))

reduce2(values, names(values), update, .init=df1)
如果要使列名恢复原样(尽管不建议使用非唯一列名),请使用
rename()


我不太明白你到底想做什么。
我想用向量中的值或带有匹配唯一标识符的df中的值来划分值是什么意思?
df2
在这里扮演什么角色?你能在你提供的数据中提供一个具体的例子,说明为了得到你想要的结果应该进行的计算吗?我很抱歉没有更清楚地描述我的意图。如果
df1
的列名与
df2
的列名匹配,则将该df1列中的值除以
df2
中的匹配值。这应该应用于
df1
中的整组值。这说明我想做什么了吗?谢谢!我可以从您的输出中看出,您的脚本生成了所需的输出,并且添加到列名中的
.1
.2
不会有问题。但是,当我运行它时,我的R在reduce_init(.x,.init,left=.left):未找到对象“foo”时抛出一个错误
错误。我更新了purrr包,但错误仍然存在。。。我的R一定有问题。尽管如此,我还是很感谢你的帮助。对不起,这里有旧代码。现在修好了。底线(带rename_at)有正确的值。实际上,它没有。。。R抛出此错误:
在mutate_at(df,vars(以(name)开头)、funs(./val))中出错:找不到函数“mutate_at”
,我认为这意味着我缺少调用该函数的包。。。但我没有进一步研究它,因为divibisan建议的
for
循环是有效的。不过我非常感谢你的帮助。谢谢啊,我明白了。您需要
库(tidyverse)
。抱歉,连续出现两个粗心的错误!好的,谢谢!在我安装了
tidyverse
之后,脚本工作得非常好。我将保留这个脚本,因为我认为它可以用于其他数据集。
      ID Conc       Eb    Eb.1  Sd Sd.1       Re Sd.2
1 nr6536  1:2 0.285714 1.14286 0.5  2.0 0.888889  3.0
2 nr8798  1:4 0.428571 1.28571 1.0  1.5 0.777778  2.0
3 nr8723  1:2 0.571429 1.42857 1.5  1.0 0.666667  1.0
4 nr8276  1:8 0.714286 1.57143 2.0  3.5 0.333333  2.5
5 nr7774  1:4 0.857143 1.71429 2.5  3.0 0.444444  1.5
6 nr0093  1:4 1.000000 1.85714 3.0  2.5 0.888889  4.0
purrr::reduce2(values, names(values), update, .init=df1) %>%
  rename_at(vars(matches("\\.\\d")), funs(str_replace(., "\\.\\d", "")))