使用 R 中另一列的条件交换列中的值
Swapping the values in columns with the condition of another column in R
对于以下数据,如果p.2
值大于0.5,我想交换第1列(b.1.1)
和第2列b.1.2
的值,
第 3 列(b.2.1)
和第 4 列 b.2.2
、第 5 列(b.3.1)
和第 6 列 b.3.2
mydata
b.1.1 b.1.2 b.2.1 b.2.2 b.3.1 b.3.2 p.1 p.2
1 0.40772028 0.43064446 0.2697412 0.9191535 0.1523922 0.7629324 0.86061981 0.1393802
2 -0.77459375 0.79860856 -0.5263932 -0.5640303 0.5131236 0.6472614 0.63494425 0.3650557
3 -0.06088828 0.42685669 -1.0643744 0.8330836 0.1184059 0.6661079 0.07382585 0.9261742
4 1.54204242 -0.08987067 -0.7365012 0.3762336 0.3781115 -0.7340340 0.65481949 0.3451805
5 -0.73397310 1.34927693 0.2202689 0.2422944 1.5267535 -0.5207967 0.54425551 0.4557445
例如,在第一行中,p.1
和p.2
之间,p.2
不大于0.5,我不交换这一行的任何值。在第三行,p.2
大于 0.5,所以,我想交换上面写的每个 beta 对的行值。
感谢您的帮助。
这是一个选项。创建一个索引以对以 'b' ('i1') 开头的列进行子集化,并创建另一个索引对行进行子集化 ('i2')。然后,split
将数据集分成list
个数据集,根据行子集后的列名相似度('i2'),循环list
,rev
删除元素,cbind
data.frames 的 list
并将其更新为原始数据集 rows/columns
i1 <- startsWith(names(mydata), "b")
i2 <- mydata$p.2 > 0.5
mydata[i2, i1] <- do.call(cbind,
lapply(split.default(mydata[i2, i1, drop = FALSE],
sub("\.\d+$", "", names(mydata)[i1])), rev))
mydata
# b.1.1 b.1.2 b.2.1 b.2.2 b.3.1 b.3.2 p.1 p.2
#1 0.4077203 0.43064446 0.2697412 0.9191535 0.1523922 0.7629324 0.86061981 0.1393802
#2 -0.7745937 0.79860856 -0.5263932 -0.5640303 0.5131236 0.6472614 0.63494425 0.3650557
#3 0.4268567 -0.06088828 0.8330836 -1.0643744 0.6661079 0.1184059 0.07382585 0.9261742
#4 1.5420424 -0.08987067 -0.7365012 0.3762336 0.3781115 -0.7340340 0.65481949 0.3451805
#5 -0.7339731 1.34927693 0.2202689 0.2422944 1.5267535 -0.5207967 0.54425551 0.4557445
另一种选择是 tidyverse
,我们将其转换为 'long' 格式,以该格式进行转换,然后重塑回 'wide' 格式
library(dplyr)
library(tidyr)
library(stringr)
library(tibble)
mydata %>%
rownames_to_column('rn') %>%
pivot_longer(cols = -c(rn, p.1, p.2)) %>%
group_by(rn, grp = str_remove(name, "\.\d+$")) %>%
mutate(value = case_when(p.2 > 0.5 ~ rev(value), TRUE ~ value)) %>%
ungroup %>%
select(-grp) %>%
pivot_wider(names_from = name, values_from = value) %>%
select(names(mydata))
# A tibble: 5 x 8
# b.1.1 b.1.2 b.2.1 b.2.2 b.3.1 b.3.2 p.1 p.2
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 0.408 0.431 0.270 0.919 0.152 0.763 0.861 0.139
#2 -0.775 0.799 -0.526 -0.564 0.513 0.647 0.635 0.365
#3 0.427 -0.0609 0.833 -1.06 0.666 0.118 0.0738 0.926
#4 1.54 -0.0899 -0.737 0.376 0.378 -0.734 0.655 0.345
#5 -0.734 1.35 0.220 0.242 1.53 -0.521 0.544 0.456
数据
mydata <- structure(list(b.1.1 = c(0.40772028, -0.77459375, -0.06088828,
1.54204242, -0.7339731), b.1.2 = c(0.43064446, 0.79860856, 0.42685669,
-0.08987067, 1.34927693), b.2.1 = c(0.2697412, -0.5263932, -1.0643744,
-0.7365012, 0.2202689), b.2.2 = c(0.9191535, -0.5640303, 0.8330836,
0.3762336, 0.2422944), b.3.1 = c(0.1523922, 0.5131236, 0.1184059,
0.3781115, 1.5267535), b.3.2 = c(0.7629324, 0.6472614, 0.6661079,
-0.734034, -0.5207967), p.1 = c(0.86061981, 0.63494425, 0.07382585,
0.65481949, 0.54425551), p.2 = c(0.1393802, 0.3650557, 0.9261742,
0.3451805, 0.4557445)), class = "data.frame", row.names = c("1",
"2", "3", "4", "5"))
另一种只使用基础而不使用正则表达式的选项是
reorderRows <- function(x, nullFrame){
for(i in length(x)){
if(x[i, 8] > 0.5)x = x[c(2,1,4,3,6,5,7,8)]
nullFrame <- rbind(nullFrame, x)
}
return(nullFrame)
}
已申请:
dat <- data.frame(matrix(rnorm(80), ncol = 8))
colnames(dat) <- c("b.1.1", "b.1.2", "b.2.1", "b.2.2",
"b.3.1", "b.3.2", "p.1", "p.2")
emptyFrame <- NULL
dat2 <- reorderRows(dat, emptyFrame)
它可能比以前的答案慢很多,但对于小数据集可能更容易修改
对于以下数据,如果p.2
值大于0.5,我想交换第1列(b.1.1)
和第2列b.1.2
的值,
第 3 列(b.2.1)
和第 4 列 b.2.2
、第 5 列(b.3.1)
和第 6 列 b.3.2
mydata
b.1.1 b.1.2 b.2.1 b.2.2 b.3.1 b.3.2 p.1 p.2
1 0.40772028 0.43064446 0.2697412 0.9191535 0.1523922 0.7629324 0.86061981 0.1393802
2 -0.77459375 0.79860856 -0.5263932 -0.5640303 0.5131236 0.6472614 0.63494425 0.3650557
3 -0.06088828 0.42685669 -1.0643744 0.8330836 0.1184059 0.6661079 0.07382585 0.9261742
4 1.54204242 -0.08987067 -0.7365012 0.3762336 0.3781115 -0.7340340 0.65481949 0.3451805
5 -0.73397310 1.34927693 0.2202689 0.2422944 1.5267535 -0.5207967 0.54425551 0.4557445
例如,在第一行中,p.1
和p.2
之间,p.2
不大于0.5,我不交换这一行的任何值。在第三行,p.2
大于 0.5,所以,我想交换上面写的每个 beta 对的行值。
感谢您的帮助。
这是一个选项。创建一个索引以对以 'b' ('i1') 开头的列进行子集化,并创建另一个索引对行进行子集化 ('i2')。然后,split
将数据集分成list
个数据集,根据行子集后的列名相似度('i2'),循环list
,rev
删除元素,cbind
data.frames 的 list
并将其更新为原始数据集 rows/columns
i1 <- startsWith(names(mydata), "b")
i2 <- mydata$p.2 > 0.5
mydata[i2, i1] <- do.call(cbind,
lapply(split.default(mydata[i2, i1, drop = FALSE],
sub("\.\d+$", "", names(mydata)[i1])), rev))
mydata
# b.1.1 b.1.2 b.2.1 b.2.2 b.3.1 b.3.2 p.1 p.2
#1 0.4077203 0.43064446 0.2697412 0.9191535 0.1523922 0.7629324 0.86061981 0.1393802
#2 -0.7745937 0.79860856 -0.5263932 -0.5640303 0.5131236 0.6472614 0.63494425 0.3650557
#3 0.4268567 -0.06088828 0.8330836 -1.0643744 0.6661079 0.1184059 0.07382585 0.9261742
#4 1.5420424 -0.08987067 -0.7365012 0.3762336 0.3781115 -0.7340340 0.65481949 0.3451805
#5 -0.7339731 1.34927693 0.2202689 0.2422944 1.5267535 -0.5207967 0.54425551 0.4557445
另一种选择是 tidyverse
,我们将其转换为 'long' 格式,以该格式进行转换,然后重塑回 'wide' 格式
library(dplyr)
library(tidyr)
library(stringr)
library(tibble)
mydata %>%
rownames_to_column('rn') %>%
pivot_longer(cols = -c(rn, p.1, p.2)) %>%
group_by(rn, grp = str_remove(name, "\.\d+$")) %>%
mutate(value = case_when(p.2 > 0.5 ~ rev(value), TRUE ~ value)) %>%
ungroup %>%
select(-grp) %>%
pivot_wider(names_from = name, values_from = value) %>%
select(names(mydata))
# A tibble: 5 x 8
# b.1.1 b.1.2 b.2.1 b.2.2 b.3.1 b.3.2 p.1 p.2
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 0.408 0.431 0.270 0.919 0.152 0.763 0.861 0.139
#2 -0.775 0.799 -0.526 -0.564 0.513 0.647 0.635 0.365
#3 0.427 -0.0609 0.833 -1.06 0.666 0.118 0.0738 0.926
#4 1.54 -0.0899 -0.737 0.376 0.378 -0.734 0.655 0.345
#5 -0.734 1.35 0.220 0.242 1.53 -0.521 0.544 0.456
数据
mydata <- structure(list(b.1.1 = c(0.40772028, -0.77459375, -0.06088828,
1.54204242, -0.7339731), b.1.2 = c(0.43064446, 0.79860856, 0.42685669,
-0.08987067, 1.34927693), b.2.1 = c(0.2697412, -0.5263932, -1.0643744,
-0.7365012, 0.2202689), b.2.2 = c(0.9191535, -0.5640303, 0.8330836,
0.3762336, 0.2422944), b.3.1 = c(0.1523922, 0.5131236, 0.1184059,
0.3781115, 1.5267535), b.3.2 = c(0.7629324, 0.6472614, 0.6661079,
-0.734034, -0.5207967), p.1 = c(0.86061981, 0.63494425, 0.07382585,
0.65481949, 0.54425551), p.2 = c(0.1393802, 0.3650557, 0.9261742,
0.3451805, 0.4557445)), class = "data.frame", row.names = c("1",
"2", "3", "4", "5"))
另一种只使用基础而不使用正则表达式的选项是
reorderRows <- function(x, nullFrame){
for(i in length(x)){
if(x[i, 8] > 0.5)x = x[c(2,1,4,3,6,5,7,8)]
nullFrame <- rbind(nullFrame, x)
}
return(nullFrame)
}
已申请:
dat <- data.frame(matrix(rnorm(80), ncol = 8))
colnames(dat) <- c("b.1.1", "b.1.2", "b.2.1", "b.2.2",
"b.3.1", "b.3.2", "p.1", "p.2")
emptyFrame <- NULL
dat2 <- reorderRows(dat, emptyFrame)
它可能比以前的答案慢很多,但对于小数据集可能更容易修改