【问题标题】:tbl_df and data.frame difference when using loops使用循环时 tbl_df 和 data.frame 的区别
【发布时间】:2015-05-02 20:42:05
【问题描述】:

我一直在遍历 dplyr tbl_df 中的值,试图打印两列的唯一组合。经过多次试验和错误,我只能通过将 tbl_df 转换回标准 data.frame 来获得所需的输出。我知道这两种结构之间的主要区别,但我仍然无法理解我看到的不同输出。

例如,使用这个数据

hospital <- rep(c("Hospital 1", "Hospital 2", "Hospital 3"), 3)
ward <- LETTERS[1:2]
hospitals <- data.frame(cbind(hospital, ward))
hospitals[order(hospitals$hospital, hospitals$ward), ]

#     hospital ward
# 1 Hospital 1    A
# 7 Hospital 1    A
# 4 Hospital 1    B
# 5 Hospital 2    A
# 2 Hospital 2    B
# 8 Hospital 2    B
# 3 Hospital 3    A
# 9 Hospital 3    A
# 6 Hospital 3    B

和下面的循环

for(hosp in unique(hospitals$hospital)){
  for(wa in unique(hospitals[hospitals$hospital==hosp, "ward"])){
    print(paste(hosp, wa, sep=" "))
    }
  }

我可以得到我想要的输出

#[1] "Hospital 1 A"
#[1] "Hospital 1 B"
#[1] "Hospital 2 B"
#[1] "Hospital 2 A"
#[1] "Hospital 3 A"
#[1] "Hospital 3 B"

但是使用相同数据的 tbl_df 我得到不同的输出

hospitals2 <- tbl_df(hospitals)

for(hosp in unique(hospitals2$hospital)){
  for(wa in unique(hospitals2[hospitals2$hospital==hosp, "ward"])){
    print(paste(hosp, wa, sep=" "))
    }
  }


#[1] "Hospital 1 A" "Hospital 1 B"
#[1] "Hospital 2 B" "Hospital 2 A"
#[1] "Hospital 3 A" "Hospital 3 B"

这不仅仅是打印上的差异,这似乎是三个二元素向量而不是六个一元素向量,并且我的后续代码仅在我在普通数据帧上运行循环时才能按预期工作。

谁能解释为什么我会看到这些差异?

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    您不能在 tbl_df 上使用子集[ 执行 for loop。文档说明了一切:

    [ 从不简化(丢弃),所以总是返回data.frame

    你看到hospitals2[hospitals2$hospital==hosp, "ward"]返回data.frame

    hospitals2[hospitals2$hospital==hosp, "ward"]
    #Source: local data frame [3 x 1]
    
    #  ward
    #1    A
    #2    B
    #3    A
    

    hospitals[hospitals$hospital==hosp, "ward"]
    #[1] A B A
    #Levels: A B
    

    例如使用[[提取列向量

    for(hosp in unique(hospitals2$hospital)){
        for(wa in unique(hospitals[hospitals$hospital==hosp,][["ward"]])){
            print(paste(hosp, wa, sep=" "))
        }
    } 
    #[1] "Hospital 1 A"
    #[1] "Hospital 1 B"
    #[1] "Hospital 2 B"
    #[1] "Hospital 2 A"
    #[1] "Hospital 3 A"
    #[1] "Hospital 3 B"
    

    【讨论】:

    • 另一个证明是,通过将drop = FALSE 添加到第一个循环,您将获得与tbl_df 对象相同的行为。 for(wa in unique(hospitals[hospitals$hospital==hosp, "ward", drop = FALSE])){
    • 非常感谢@Khashaa,我已经在文档中阅读过,但完全错过了相关性。
    猜你喜欢
    • 2017-10-12
    • 2020-01-21
    • 2015-09-15
    • 1970-01-01
    • 1970-01-01
    • 2019-04-21
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多