根据条件仅将 R 中的某些行转换为绝对值

Posted

技术标签:

【中文标题】根据条件仅将 R 中的某些行转换为绝对值【英文标题】:Convert into absolute values only certain rows in R based on conditions 【发布时间】:2021-07-28 16:14:51 【问题描述】:

我有这个数据集

df <- data.frame(PatientID = c("0002" ,"0002", "0005", "0005" ,"0009" ,"0009" ,"0018", "0018" ,"0020" ,"0027", "0039" ,"0039" ,"0042", "0043" ,"0043" ,"0045", "0046", "0046" ,"0048" ,"0048", "0055"),
                 Timepoint= c("A", "B", "A", "B", "A", "B", "A", "B", "A", "A", "A", "B", "A", "A", "B",  "A",  "A", "B", "A", "B", "A"),
                 A = c(NA , 977.146 , NA , 964.315 ,NA , 952.311 , NA , 950.797 , 958.975  ,960.712  ,NA , 947.465 , -902.852 , NA,  985.124  ,NA , 930.141 ,-1007.790 , 948.848, 1027.110 , -999.414),
                 B = c(998.988 , NA , 998.680 , NA , NA ,1020.560 , 947.751 ,1029.560 , 955.540 , 911.606 , 964.039   ,    NA,  988.087 , -902.367 , 959.338 ,1029.050 , 925.162 , 987.374 ,1066.400  ,957.512 , 917.597),
                 C = c( NA , 987.140 , 961.810 , 929.466 , 978.166, 1005.820  ,925.752 , -969.469 , 943.398  ,936.034,  -965.292 , 996.404 , 920.610 , 967.047  ,986.565 , 913.517 , -893.428 , 921.606 , NA , 929.590  ,950.493), 
                 D = c(975.634 , 987.140 , 961.810 , 929.466 , 978.166, 1005.820 , 925.752 , 969.469  ,943.398 , NA , 965.292 , 996.404 , NA , 967.047 , 986.565 , NA , 893.428 , 921.606 , 976.192 , 929.590 , 950.493),
                 E = c(1006.330, -1028.070 , NA , -954.274 ,1005.910  ,949.969 , 992.820 , 977.048  ,934.407 , 948.913 , NA , NA , NA,  961.375  ,-955.296 , 961.128  ,998.119 ,1009.110 , 994.891 ,-1000.170  ,982.763),
                 G= c(NA , 958.990 , NA , NA , 924.680 , 955.927 , NA , 949.384  ,973.348 , -984.392 , 943.894 , 961.468 , -995.368 , 994.997 , NA , -979.454 , 952.605 , NA  ,   NA, NA , 956.507), stringsAsFactors = F)

而且我只需要将属于df$Timepoint==B的数字转换为绝对值

你有什么推荐的?

谢谢

【问题讨论】:

【参考方案1】:

我们可以使用 dplyr 和 mutate() 以及 cross() 和 ifelse() 将条件合并到单个衬里,而无需创建中间对象:

df %>% mutate(across(A:G, ~ifelse(Timepoint=='B', abs(.x), .x)))

   PatientID Timepoint        A        B        C        D        E        G
1       0002         A       NA  998.988       NA  975.634 1006.330       NA
2       0002         B  977.146       NA  987.140  987.140 1028.070  958.990
3       0005         A       NA  998.680  961.810  961.810       NA       NA
4       0005         B  964.315       NA  929.466  929.466  954.274       NA
5       0009         A       NA       NA  978.166  978.166 1005.910  924.680
6       0009         B  952.311 1020.560 1005.820 1005.820  949.969  955.927
7       0018         A       NA  947.751  925.752  925.752  992.820       NA
8       0018         B  950.797 1029.560  969.469  969.469  977.048  949.384
9       0020         A  958.975  955.540  943.398  943.398  934.407  973.348
10      0027         A  960.712  911.606  936.034       NA  948.913 -984.392
11      0039         A       NA  964.039 -965.292  965.292       NA  943.894
12      0039         B  947.465       NA  996.404  996.404       NA  961.468
13      0042         A -902.852  988.087  920.610       NA       NA -995.368
14      0043         A       NA -902.367  967.047  967.047  961.375  994.997
15      0043         B  985.124  959.338  986.565  986.565  955.296       NA
16      0045         A       NA 1029.050  913.517       NA  961.128 -979.454
17      0046         A  930.141  925.162 -893.428  893.428  998.119  952.605
18      0046         B 1007.790  987.374  921.606  921.606 1009.110       NA
19      0048         A  948.848 1066.400       NA  976.192  994.891       NA
20      0048         B 1027.110  957.512  929.590  929.590 1000.170       NA
21      0055         A -999.414  917.597  950.493  950.493  982.763  956.507

【讨论】:

这不太行,因为 B 值仍然显示负值? - 感谢您的回答! 我复制了错误的输出数据,但代码没问题。请看现在是否可以【参考方案2】:

我不确定这是否是你想要的,但你可以使用这个:

df[df$Timepoint=="B",c(3:8)] <- apply(df[df$Timepoint=="B",c(3:8)], 2, abs)

columns <- c("A", "B", "C", "D", "E", "G")
df[df$Timepoint=="B",columns] <- apply(df[df$Timepoint=="B",columns], 2, abs)

【讨论】:

【参考方案3】:

这是一个 data.table 解决方案:

setDT(df)
cols <-  sapply(df, is.numeric)
cols <- names(cols)[cols]

df[Timepoint == 'B', (cols) := lapply(.SD, FUN = abs),.SDcols = cols]

【讨论】:

请注意.SDcols 接受一个函数来选择列,即.SDcols = is.numeric 就足够了。干杯【参考方案4】:

不是世界上最高效的代码,但这会起作用

df$A[df$Timepoint == "B"] <- abs(df$A)
df$B[df$Timepoint == "B"] <- abs(df$B)
df$C[df$Timepoint == "B"] <- abs(df$C)
df$D[df$Timepoint == "B"] <- abs(df$D)
df$E[df$Timepoint == "B"] <- abs(df$E)
df$G[df$Timepoint == "B"] <- abs(df$G)

【讨论】:

这对任何人来说都不是一个有用的解决方案

以上是关于根据条件仅将 R 中的某些行转换为绝对值的主要内容,如果未能解决你的问题,请参考以下文章

将值从字段转换为绝对值

找到根据矩阵中特定列中的行之间的绝对差排序的子集

Swift - 转换为绝对值

2021年大数据Hive:Hive的内置函数(数学字符串日期条件转换行转列)

R语言怎么按条件删除某些行?

Vue Router 相对路径转绝对路径