【问题标题】:Apply conditional selection to sequence of columns R将条件选择应用于列序列 R
【发布时间】:2016-06-20 06:12:46
【问题描述】:

我使用来自 NHANES 牙周数据集 (https://wwwn.cdc.gov/Nchs/Nhanes/2009-2010/OHXPER_F.htm) 的数据,在清理它以仅保留“pc”变量后,我有一个 df=setPD 168 列,其中包括 6 个测量值(pcd、pcm、pcs、pcp、 pcl, pca) 大约 28 颗牙齿,编号从 #02 到 #31

#names(setPD)
  [1] "ohx02pcd" "ohx02pcm" "ohx02pcs" "ohx02pcp" "ohx02pcl" "ohx02pca" "ohx03pcd" "ohx03pcm" "ohx03pcs" "ohx03pcp" "ohx03pcl" "ohx03pca"
 [13] "ohx04pcd" "ohx04pcm" "ohx04pcs" "ohx04pcp" "ohx04pcl" "ohx04pca" "ohx05pcd" "ohx05pcm" "ohx05pcs" "ohx05pcp" "ohx05pcl" "ohx05pca"
 [25] "ohx06pcd" "ohx06pcm" "ohx06pcs" "ohx06pcp" "ohx06pcl" "ohx06pca" "ohx07pcd" "ohx07pcm" "ohx07pcs" "ohx07pcp" "ohx07pcl" "ohx07pca"
 [37] "ohx08pcd" "ohx08pcm" "ohx08pcs" "ohx08pcp" "ohx08pcl" "ohx08pca" "ohx09pcd" "ohx09pcm" "ohx09pcs" "ohx09pcp" "ohx09pcl" "ohx09pca"
 [49] "ohx10pcd" "ohx10pcm" "ohx10pcs" "ohx10pcp" "ohx10pcl" "ohx10pca" "ohx11pcd" "ohx11pcm" "ohx11pcs" "ohx11pcp" "ohx11pcl" "ohx11pca"
 [61] "ohx12pcd" "ohx12pcm" "ohx12pcs" "ohx12pcp" "ohx12pcl" "ohx12pca" "ohx13pcd" "ohx13pcm" "ohx13pcs" "ohx13pcp" "ohx13pcl" "ohx13pca"
 [73] "ohx14pcd" "ohx14pcm" "ohx14pcs" "ohx14pcp" "ohx14pcl" "ohx14pca" "ohx15pcd" "ohx15pcm" "ohx15pcs" "ohx15pcp" "ohx15pcl" "ohx15pca"
 [85] "ohx18pcd" "ohx18pcm" "ohx18pcs" "ohx18pcp" "ohx18pcl" "ohx18pca" "ohx19pcd" "ohx19pcm" "ohx19pcs" "ohx19pcp" "ohx19pcl" "ohx19pca"
 [97] "ohx20pcd" "ohx20pcm" "ohx20pcs" "ohx20pcp" "ohx20pcl" "ohx20pca" "ohx21pcd" "ohx21pcm" "ohx21pcs" "ohx21pcp" "ohx21pcl" "ohx21pca"
[109] "ohx22pcd" "ohx22pcm" "ohx22pcs" "ohx22pcp" "ohx22pcl" "ohx22pca" "ohx23pcd" "ohx23pcm" "ohx23pcs" "ohx23pcp" "ohx23pcl" "ohx23pca"
[121] "ohx24pcd" "ohx24pcm" "ohx24pcs" "ohx24pcp" "ohx24pcl" "ohx24pca" "ohx25pcd" "ohx25pcm" "ohx25pcs" "ohx25pcp" "ohx25pcl" "ohx25pca"
[133] "ohx26pcd" "ohx26pcm" "ohx26pcs" "ohx26pcp" "ohx26pcl" "ohx26pca" "ohx27pcd" "ohx27pcm" "ohx27pcs" "ohx27pcp" "ohx27pcl" "ohx27pca"
[145] "ohx28pcd" "ohx28pcm" "ohx28pcs" "ohx28pcp" "ohx28pcl" "ohx28pca" "ohx29pcd" "ohx29pcm" "ohx29pcs" "ohx29pcp" "ohx29pcl" "ohx29pca"
[157] "ohx30pcd" "ohx30pcm" "ohx30pcs" "ohx30pcp" "ohx30pcl" "ohx30pca" "ohx31pcd" "ohx31pcm" "ohx31pcs" "ohx31pcp" "ohx31pcl" "ohx31pca"

我正在尝试在每组六列中应用条件选择。这是:

transmute(setPD,PD02 = ifelse(setPD$ohx02pcd >5 | 
    setPD$ohx02pcm>5 |setPD$ohx02pcs >5| 
    setPD$ohx02pcp >5 | setPD$ohx02pcl >5 | 
    setPD$ohx02pca >5, 1, 0))

那么下一颗牙(03)我得再写一遍:

transmute(setPD,PD03 = ifelse(setPD$ohx03pcd >5 |
   setPD$ohx03pcm>5|setPD$ohx03pcs >5|
   setPD$ohx03pcp >5|setPD$ohx03pcl >5|
   setPD$ohx03pca >5, 1, 0))

我首先尝试以更有效的方式进行条件选择,例如:

transmute(setPD,PD02 = ifelse(list(setPD$ohx02pcd:setPD$ohx02pcp) >5, 1, 0))

但它不起作用。

然后我正在寻找一种方法来编写一个循环,在每颗牙齿上执行此操作,而无需编写 28 次!! 我想在 for 循环中应用 dplyr 的选择功能,但我不知道该怎么做。 最后,我想得到我用 transmute 制作的所有新列,并说如果 28 列中至少有 2 列是 1,那么我有病,如果

**注意:如果要获取数据集,可以从 CDC.org 开放获取: https://wwwn.cdc.gov/Nchs/Nhanes/2009-2010/OHXPER_F.htm**

【问题讨论】:

  • 您能否提供带有示例数据的可重现代码?
  • @user3495945 - 只是一个评论 - 我几乎从不从保管箱或文件共享网站下载文件,而不知道是谁把它们放在那里的。我怀疑这里的许多人都会有同样的感觉。您有责任提供一个通常可以直接从问题中复制和粘贴的可重现代码的小示例。
  • @thelatemail 我是 R 新手。你如何建议这样做?正如我在问题中所说,数据集可从 CDC.org 网站公开获得,这应该是一个非常安全的来源wwwn.cdc.gov/Nchs/Nhanes/2009-2010/OHXPER_F.htm
  • @user3495945 - 请参阅此处的常见问题解答 - stackoverflow.com/questions/5963269/…
  • dput(droplevels(your_data[1:6, 1:10])) 这样的东西怎么样。应该是可重复的并且非常短。

标签: r for-loop conditional dplyr


【解决方案1】:

首先,有必要指出is A true OR is B true OR is C true 形式的逻辑语句等价于询问is ANY of A,B,C true?我们可以使用它来简化语句setPD$ohx02pcd >5 | setPD$ohx02pcm>5 |setPD$ohx02pcs >5| ...,以询问这些列中的任何一个的值是否大于 5。

例如,让我们首先关注齿数 02。要获取与这颗牙齿有关的所有列,我们可以使用grep 来获取列名向量。这可以通过

来实现
current_tooth <- grep("02", names(setPD), value = T)

请注意,如果数据中有任何其他列包含字符串02,这些列也会显示出来。您的数据中似乎并非如此,但值得在这里指出,以防其他人使用它,这适用于其他数据集。

现在,我们可以使用这些名称来对数据框进行子集化。例如,

 setPD[,current_tooth]

会给你相应的列。在每一行中,我们要检查上述任何条件是否为真。给定一个逻辑语句向量,我们可以使用函数any 检查它们是否为真。要逐行遍历数据帧并应用函数,我们可以使用apply,例如在

setPD$PD02 <- 
  apply(setPD[,grep("02", names(setPD), value = T)], 1, function(x) any(x>5))

现在,以上仅适用于一颗牙齿,即02。对所有牙齿执行此操作的一种方法是创建一个包含所有牙齿指示符的向量,并使用它来循环上述行,在每次迭代中替换上述grep 调用中的"02" 并使用assign 或类似的东西获得正确的变量名称。更优雅、更有效的方法是对长数据使用相同的原理。考虑以下几点:

library(reshape2)
library(dplyr)

m <- melt(setPD, id.vars="SEQN")
m$num <- substr(m$variable, 4,5) # be careful here and check output!
m <- m %>% group_by(num) %>% mutate(PS = any(value>5))
m$num <- paste0("PS", m$num)
md <- dcast(m, SEQN ~ num, value.var = "PS")
setPD <- merge(setPD, md, by="SEQN")

这会首先融合您的数据并创建一个变量num 来指示您的牙齿。再次,确保这有效。我使用了这样一个事实,即在您的数据中,齿数都出现在字符串的第 4 位和第 5 位。确保这是真的,否则调整代码。然后我创建一个变量PS,它指示是否有任何包含牙齿标识符的列的值大于5。最后但并非最不重要的一点是,我重铸了数据,以便您在列中再次获得PD02, PD03, etc 的值,之前我将其合并到旧数据集。 paste0 的行仅创建您想要的变量名称。

【讨论】:

  • 太棒了!!!!您认为如何将您的 grep 方法应用于所有列,而不是手动为“02”然后为“03”等等?
  • 好吧,如果您仍然想单独评估每颗牙齿的逻辑语句,那么您应该使用我的第二种方法,或者围绕语句进行循环。如果您想一次评估所有牙齿,您可以使用grep("0[1-9]", names(setPD), value = T)。但同样,请检查这是否检索到不需要的列。
  • @coffeeinjunky 我试过了,它返回了一个数据帧,每行有 28 个 PS 值是“6”。有些东西不起作用。
  • 条件(值>5)的牙齿数量似乎在标题为“m$value”的列中,但没有被重铸
  • 您能否发布更广泛的数据样本来重现此行为?在您当前的样本中,仅包含 02 颗牙齿。
猜你喜欢
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 2015-03-15
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
相关资源
最近更新 更多