将列值与行总和进行比较

3

我正在尝试使用rowSums,但使用比较对值进行条件判断。

这是我的数据框的一个例子,基于调查。其中行代表参与者,列代表孩子的出生日期。

  b3_01 b3_02 b3_03 b3_04 b3_05 b3_06
1  1360  1360  1266  1228  1181  1158    
2  1362  1342  1301  1264  1245  1191 
3  1379    NA    NA    NA    NA    NA  
4  1355  1330  1293  1293  1227  1208  
5  1391  1371  1358  1334  1311  1311

在这里,类似的日期指的是双胞胎。我想要做的是创建一个新的列,告诉我每行这些列的值相似的次数。这将给我一些类似于这样的东西:
  b3_01 b3_02 b3_03 b3_04 b3_05 b3_06 twins
1  1360  1360  1266  1228  1181  1158     1
2  1362  1342  1301  1264  1245  1191     0
3  1379    NA    NA    NA    NA    NA     0
4  1355  1330  1293  1293  1227  1208     1
5  1391  1371  1358  1334  1311  1311     1

编辑:抱歉,我忘了说如果任何数字出现3次或更多次,它不应计为孪生数。最终目标是有4列:一个用于单个数字(每个数字仅出现一次),一个用于孪生数,一个用于三胞胎(如果任何数字出现三次),以及一个用于四胞胎。

我正在使用dplyr。由于数据框非常大,我需要指定要进行比较的列的范围。我已尝试以下代码及其变体:

twins<-df%>%
  mutate(twins= rowSums(select(.,starts_with("b3_")) == select(.,starts_with("b3_")),na.rm=TRUE))

这种方法不起作用。我也尝试了其他函数,但无法找到解决方案。

你有任何想法如何实现吗?我感觉解决方案很简单,但我是R的绝对初学者。


1
如果一行有三个相同的数字(其他数字都不同),您会把它们视为一个对子还是两个对子?更普遍地说,如果一行包含n个相同的值,您想要计算n-1对还是1对? - Jonas
我不会把它们视为孪生。理想情况下,我想创建4个新列:1个用于单例(每个数字仅出现一次),2个用于孪生(如果任何数字仅出现两次),3个用于三胞胎(如果任何数字出现三次),以及一个用于四胞胎。这是否验证或使您的答案无效?顺便感谢您。 - Maxime Besson
1
那么我在答案中使用table的逻辑非常好。你将会得到单独项的数量,即sum(table==1),双胞胎的数量为sum(table==2),三胞胎的数量为sum(table==3)。我会更新我的答案。 - Jonas
4个回答

2
一个简单的解决方案是:
twins <- df%>%
  mutate(twins = apply(., 1, function(x) sum(duplicated(x, incomparables=NA))))

我非常喜欢你的解决方案!不过,你知道如何仅计算重复两次的值吗?我想为重复两次、三次或四次的值创建单独的列。(请参见编辑) - Maxime Besson

1

参考我的评论,并假设一行中有 n 个相同的值被计算为 n-1 对双胞胎,定义:

countTwins <- function(row) {
  length(row)-length(unique(row))
}

并获取列 twins 如下:
twinCol <- apply(df,1,countTwins)

如果您想将具有相同值的n个元素视为1个双胞胎,请使用以下函数:
countTwins2 <- function(row) {
  sum(table(unname(unlist(row)))>1)
}

根据我的评论更新:
countSinglesTwinsAndTriplets <- function(row) {
  tt <- table(unname(unlist(row)))
  c(sum(tt==1),sum(tt==2),sum(tt==3)) #nr of singletons,twins,triplets
}

addCols <- setNames(data.frame(t(apply(df,1,countSinglesTwinsAndTriplets))),c("singletons","twins","triplets"))

1
额外解决方案
基础
df$twins <- apply(df, 1, function(x) length(x) - length(unique(x)) - sum(is.na(x)) + any(is.na(x)))

  b3_01 b3_02 b3_03 b3_04 b3_05 b3_06 twins
1  1360  1360  1266  1228  1181  1158     1
2  1362  1342  1301  1264  1245  1191     0
3  1379    NA    NA    NA    NA    NA     0
4  1355  1330  1293  1293  1227  1208     1
5  1391  1371  1358  1334  1311  1311     1

1
与 @Taufi 使用的类似逻辑,但增加了 purrr
df %>%
 mutate(twins = pmap(across(everything()), ~ sum(duplicated(na.omit(c(...))))))

  b3_01 b3_02 b3_03 b3_04 b3_05 b3_06 twins
1  1360  1360  1266  1228  1181  1158     1
2  1362  1342  1301  1264  1245  1191     0
3  1379    NA    NA    NA    NA    NA     0
4  1355  1330  1293  1293  1227  1208     1
5  1391  1371  1358  1334  1311  1311     1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接