我有许多数据帧(96),它们的列分别为0和1。如果数据帧的任何一列中有多个“ 1”,我想用相等的分数替换1,以便该列中的值之和为1,如下面的代码所示。
v1 <- c(0, 1, 0, 1, 1, 0)
v2 <- c(0, 0, 1, 0, 0, 0)
v3 <- c(0, 0, 1, 1, 0, 0)
df1 <- data.frame(v1, v2, v3)
df2 <-data.frame(v3, v3, v1)
df3 <- data.frame(v1, v3, v1)
new.df1 <- t(apply(df1, 2, FUN = function(x) {
if(sum(x==1, na.rm=TRUE) ==2) replace(x, x==1, 0.5)
else if (sum(x==1, na.rm=TRUE)==3) replace( x, x==1, 1/3)
else x}))
new.df2 <- t(apply(df2, 2, FUN = function(x) {
if(sum(x==1, na.rm=TRUE) ==2) replace(x, x==1, 0.5)
else if (sum(x==1, na.rm=TRUE)==3) replace( x, x==1, 1/3)
else x}))
new.df3 <- t(apply(df3, 2, FUN = function(x) {
if(sum(x==1, na.rm=TRUE) ==2) replace(x, x==1, 0.5)
else if (sum(x==1, na.rm=TRUE)==3) replace( x, x==1, 1/3)
else x}))
像上面的示例一样,我可以用蛮力创建自己想要的东西,但是必须有更好的方法(更简洁)。非常感谢您的帮助。
答案 0 :(得分:1)
将代码存储在函数中,将数据帧存储在列表中,然后使用lapply在函数中遍历每个列表元素。
recalc <- function(df) {
t(apply(df, 2, FUN = function(x) {
if(sum(x==1, na.rm=TRUE) ==2) replace(x, x==1, 0.5)
else if (sum(x==1, na.rm=TRUE)==3) replace( x, x==1, 1/3)
else x}))
}
lapply(dflist, function(df) recalc(df))
[[1]]
[,1] [,2] [,3] [,4] [,5] [,6]
v1 0 0.3333333 0.0 0.3333333 0.3333333 0
v2 0 0.0000000 1.0 0.0000000 0.0000000 0
v3 0 0.0000000 0.5 0.5000000 0.0000000 0
[[2]]
[,1] [,2] [,3] [,4] [,5] [,6]
v3 0 0.0000000 0.5 0.5000000 0.0000000 0
v3.1 0 0.0000000 0.5 0.5000000 0.0000000 0
v1 0 0.3333333 0.0 0.3333333 0.3333333 0
[[3]]
[,1] [,2] [,3] [,4] [,5] [,6]
v1 0 0.3333333 0.0 0.3333333 0.3333333 0
v3 0 0.0000000 0.5 0.5000000 0.0000000 0
v1.1 0 0.3333333 0.0 0.3333333 0.3333333 0
答案 1 :(得分:1)
与其他答案类似,但更加模块化和功能的改进版本:
## Put your data frames in a list
# df_list = list(df1, df2, df3)
df_list = mget(ls(pattern = "df[0-9]"))
## Write a function to modify one column
replace_ones = function(x) {
sx = sum(x == 1, na.rm = TRUE)
if(sx > 1) {
x = replace(x, x == 1, 1 / sx)
}
return(x)
}
## Wrap it to modify a data frame:
replace_ones_df = function(df) {
df[] = lapply(df, replace_ones)
return(df)
}
## Apply the function to all columns of all data frames:
result_list = lapply(df_list, replace_ones_df)
# $df1
# v1 v2 v3
# 1 0.0000000 0 0.0
# 2 0.3333333 0 0.0
# 3 0.0000000 1 0.5
# 4 0.3333333 0 0.5
# 5 0.3333333 0 0.0
# 6 0.0000000 0 0.0
#
# $df2
# v3 v3.1 v1
# 1 0.0 0.0 0.0000000
# 2 0.0 0.0 0.3333333
# 3 0.5 0.5 0.0000000
# 4 0.5 0.5 0.3333333
# 5 0.0 0.0 0.3333333
# 6 0.0 0.0 0.0000000
#
# $df3
# v1 v3 v1.1
# 1 0.0000000 0.0 0.0000000
# 2 0.3333333 0.0 0.3333333
# 3 0.0000000 0.5 0.0000000
# 4 0.3333333 0.5 0.3333333
# 5 0.3333333 0.0 0.3333333
# 6 0.0000000 0.0 0.0000000
答案 2 :(得分:1)
不是手动计算二进制列中的1的数量并使用if/else
,而是将放置在list
中的数据集除以列总和(colSums
)
lapply(mget(paste0("df", 1:3)), function(x) x/colSums(x)[col(x)])
#$df1
# v1 v2 v3
#1 0.0000000 0 0.0
#2 0.3333333 0 0.0
#3 0.0000000 1 0.5
#4 0.3333333 0 0.5
#5 0.3333333 0 0.0
#6 0.0000000 0 0.0
#$df2
# v3 v3.1 v1
#1 0.0 0.0 0.0000000
#2 0.0 0.0 0.3333333
#3 0.5 0.5 0.0000000
#4 0.5 0.5 0.3333333
#5 0.0 0.0 0.3333333
#6 0.0 0.0 0.0000000
#$df3
# v1 v3 v1.1
#1 0.0000000 0.0 0.0000000
#2 0.3333333 0.0 0.3333333
#3 0.0000000 0.5 0.0000000
#4 0.3333333 0.5 0.3333333
#5 0.3333333 0.0 0.3333333
#6 0.0000000 0.0 0.0000000