【问题标题】:How do I use two dataframe conditions with for loop to get nrow(output)如何在 for 循环中使用两个数据帧条件来获取 nrow(output)
【发布时间】:2021-10-27 20:45:58
【问题描述】:

我对 R 很不友好,所以请容忍我的措辞。我有一个来自 csv 的 df,它有 11 个变量的 106 个 obs。我只关心其中的 2 个变量,所以我创建了一个名为“df”的新 df。

bc=read.csv("---.csv")
df=cbind.data.frame('A'=bc$A,'B'=bc$B)

#Example of the new df:

A       B
mass    0.1
mass    0.2
height  0.5
height  0.3
color   0.9
color   0.1

然后我制作了 (4) 个向量,每个向量都基于可以满足 (2) 个同时条件的行数:大于 OET 或小于 OET 并且类型是“质量”或类型不是“质量”。

TP= df[df$B>=i & df$A=="mass",]     
TN= df[df$B<=i & df$A!="mass",]
FP= df[df$B<=i & df$A!="mass",]
FN= df[df$B<=i & df$A=="mass",]

我想我想使用一个 for 循环,这样我就可以为每个 B 条件,每个 i 都有一个向量。如果我将“i”设置为一个值,向量将给我所有适合的行,然后 nrow("vector") 来查看有多少行 - 但我无法将所有 106 个 df$B 值输入 i。我确实打印了看我是否可以工作,它表明我可以从 df$B 获取每一行。于是我用 df$A 尝试了一半的 TP 向量。那行得通。现在我单独尝试了 df$B 部分。但这给了我所有 106 个 obs,我知道这是错误的,因为非循环 TP 给了我 21 个 obs。代码的最终目标是为满足我的 (2) 条件的每个 df$B 提供一些 TP 和 TN,以便我可以将它们插入到 ggplot 的另一个函数中。 [如 Y=TP/TP-TN]

N=c(df$B)
for(i in N){
print(paste(i))
}   
# worked
          
for(i in N){
TPA=df[df$A=="mass",]
TP=nrow(TPA)
}
# worked

for(i in N){
TPB=df[df$B>=i,]
TP=nrow(TPB)
}
#ran but did not do what I wanted

我想我的问题是如何针对每个 df$B(全部 106 个)运行 df$B 的所有行并存储它们?

当i = df$B[1]时,df$B有多少行>i

当i=df$B[2]时,df$B有多少行>i

从这样的公式,我想要如下输出:

results=data.frame(matrix(nrow=,ncol=4))
colnames(results)=c("A","B","TP","TN")
B=rep(c("mass","not mass"),each=106)
N=c(df$B)
for(i in N){
    TPC=df[df$A=='mass' & df$B>=i,]
    TP=nrow(TPC)
    TNC=df[df$A!='mass' & df$B<=i,]
    TN=nrow(TNC)
    } 
results=cbind.data.frame(B,A,results)

B       A        TP   TN
mass    df$B[1]  21   0
mass    df$B[2]  18   12
...
notmass df$B[1]  1    11
notmass df$B[2]  3    10
...

如果您读到这里,谢谢!任何方向或答案将不胜感激!

【问题讨论】:

  • 我不完全确定,但我认为您的 FN= df[df$B&lt;=i &amp; df$A=="mass",] 行中可能存在拼写错误。你的意思是df$B &gt;= i 吗?
  • 请澄清您的具体问题或提供其他详细信息以准确突出您的需求。正如目前所写的那样,很难准确地说出你在问什么。

标签: r dataframe loops for-loop


【解决方案1】:

我不确定我是否正确理解了你的混淆矩阵的术语,但这里有一个对我来说似乎对 R 更惯用的通用方法的建议,在这种情况下使用 dplyrtidyr

从您的数据开始:

df1 <- data.frame(
  stringsAsFactors = FALSE,
                 A = c("mass", "mass", "height", "height", "color", "color"),
                 B = c(0.1, 0.2, 0.5, 0.3, 0.9, 0.1)
)

我们可以添加一个逻辑mass 变量来捕获A 是否等于“质量”。我们还可以列出 B 的值以供以后使用。

df1$mass = df1$A == "mass" 
B_val = sort(unique(df1$B))

下面,我为B_val 的每个值制作一个数据副本,并使用dplyr::case_when 来定义混淆矩阵的值。 (我怀疑我没有这些权利,但应该很容易解决。)

最后,我在底部计算出现了多少组合,然后将数据重塑为更宽的格式,并为每个结论命名列。

library(dplyr); library(tidyr)
df1 %>%
  crossing(B_val) %>%
  mutate(type = case_when(
    B >= B_val & mass  ~ "TP",
    B <= B_val & !mass ~ "TN",
    B <= B_val & mass  ~ "FP",
    B >= B_val & !mass ~ "FN",
    TRUE ~ "undefined"
  )) %>%
  
  count(mass, B_val, type) %>%
  # group_by(mass, B_val) %>%   #un-comment these lines for proportions
  # mutate(n = n / sum(n)) %>%
  pivot_wider(names_from = type, values_from = n)

这会产生以下输出:

# A tibble: 10 x 6
   mass  B_val    FN    TN    TP    FP
   <lgl> <dbl> <int> <int> <int> <int>
 1 FALSE   0.1     3     1    NA    NA
 2 FALSE   0.2     3     1    NA    NA
 3 FALSE   0.3     2     2    NA    NA
 4 FALSE   0.5     1     3    NA    NA
 5 FALSE   0.9    NA     4    NA    NA
 6 TRUE    0.1    NA    NA     2    NA
 7 TRUE    0.2    NA    NA     1     1
 8 TRUE    0.3    NA    NA    NA     2
 9 TRUE    0.5    NA    NA    NA     2
10 TRUE    0.9    NA    NA    NA     2

或者如果看比例:

   mass  B_val    FN    TN    TP    FP
   <lgl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 FALSE   0.1  0.75  0.25  NA    NA  
 2 FALSE   0.2  0.75  0.25  NA    NA  
 3 FALSE   0.3  0.5   0.5   NA    NA  
 4 FALSE   0.5  0.25  0.75  NA    NA  
 5 FALSE   0.9 NA     1     NA    NA  
 6 TRUE    0.1 NA    NA      1    NA  
 7 TRUE    0.2 NA    NA      0.5   0.5
 8 TRUE    0.3 NA    NA     NA     1  
 9 TRUE    0.5 NA    NA     NA     1  
10 TRUE    0.9 NA    NA     NA     1  

【讨论】:

  • 我想就是这样!
猜你喜欢
  • 2019-04-01
  • 2019-11-28
  • 2021-05-29
  • 2020-05-13
  • 2021-10-10
  • 2019-06-20
  • 1970-01-01
  • 2020-04-29
  • 1970-01-01
相关资源
最近更新 更多