【问题标题】:How to create rows using a loop?如何使用循环创建行?
【发布时间】:2020-02-10 09:12:05
【问题描述】:

我有一个如下所示的数据集:

ColA; ColB; ColC;
PAR; BKK; Y;
BKK; SYD; Y;  
NYC; LAX; Y;
LAX; SFO; Y;

我想复制 ColC==Y 的行,如果一行的 colB==另一行的 colA,那么我想用这些值创建一行:第一行的 colA 和第二行的 colB。在我们的示例中,它看起来像这样:

ColA; ColB; ColC;
PAR; SYD; Y; 
NYC; SFO; Y;

这些行将被添加到主数据集中。

我曾尝试使用“for”循环,并生成一个临时数据集来 rbind 两者,但它不起作用。

for (i in 1:nrow(maindataset)){
    for (j in (i+1):nrow(maindataset)-1){
        if (maindataset$colB[i]==maindataset$colA[j] & maindataset$colC[i]==maindataset$colC[j]) {
        newDF<-data.frame(ColA=maindataset$colA[i],ColB=maindataset$colA[j],ColC=maindataset$colA[j],stringsAsFactors = FALSE)
    maindataset<-rbind(maindataset,newDF)
}
}
}

我不确定循环是否是最佳解决方案。你知道我可以解决它的方法吗?

谢谢!

【问题讨论】:

    标签: r loops


    【解决方案1】:

    通常,当您需要将数据集中的两列相等时,请考虑进行连接。在这种情况下,首先过滤掉colBcolA 中存在的行,然后您可以与原始数据集进行左连接。那应该给你你需要的行。然后,您可以在选择适当的行并根据需要重命名它们后,执行rbind 将它们添加到原始数据集中:

    library(dplyr)
    #> 
    #> Attaching package: 'dplyr'
    #> The following objects are masked from 'package:stats':
    #> 
    #>     filter, lag
    #> The following objects are masked from 'package:base':
    #> 
    #>     intersect, setdiff, setequal, union
    set.seed(123)
    df <- tibble(colA=sample(state.abb,20,replace = T),
                 colB=sample(state.abb,20,replace = T)) %>% 
      filter(colA!=colB)
    df # Sample dataframe with two columns having data from same superset
    #> # A tibble: 19 x 2
    #>    colA  colB 
    #>    <chr> <chr>
    #>  1 NM    CT   
    #>  2 IA    TN   
    #>  3 IN    FL   
    #>  4 AZ    ME   
    #>  5 TN    OK   
    #>  6 WY    IN   
    #>  7 TX    KY   
    #>  8 OR    TX   
    #>  9 IN    RI   
    #> 10 MO    ID   
    #> 11 MT    IA   
    #> 12 NE    NY   
    #> 13 CA    TN   
    #> 14 NE    VT   
    #> 15 NV    CT   
    #> 16 NH    SD   
    #> 17 OH    GA   
    #> 18 DE    MN   
    #> 19 MT    NE
    
    df1 <- df %>% 
      filter(colB %in% colA) %>% # filter the rows where `colB` is present in `colA`
      left_join(df, by=c('colB'='colA')) # Left join with original dataset
    df1
    #> # A tibble: 8 x 3
    #>   colA  colB  colB.y
    #>   <chr> <chr> <chr> 
    #> 1 IA    TN    OK    
    #> 2 WY    IN    FL    
    #> 3 WY    IN    RI    
    #> 4 OR    TX    KY    
    #> 5 MT    IA    TN    
    #> 6 CA    TN    OK    
    #> 7 MT    NE    NY    
    #> 8 MT    NE    VT
    
    df1 %>% 
      select(-colB) %>% 
      rename(colB=colB.y) $ colB.y is the column you need, so rename it and drop the other one
    #> # A tibble: 8 x 2
    #>   colA  colB 
    #>   <chr> <chr>
    #> 1 IA    OK   
    #> 2 WY    FL   
    #> 3 WY    RI   
    #> 4 OR    KY   
    #> 5 MT    TN   
    #> 6 CA    OK   
    #> 7 MT    NY   
    #> 8 MT    VT
    

    reprex package (v0.3.0) 于 2020-02-10 创建

    【讨论】:

      【解决方案2】:

      您似乎尝试获取newDF,但遇到了一些困难。这是一个可能对您有帮助的基本 R 解决方案

      newDF <- with(subset(df,ColC == "Y"), 
                    data.frame(ColA = ColA[na.omit(p <-match(ColA,ColB))],
                               ColB = ColB[which(!is.na(p))],
                               ColC = "Y"))
      

      这样

      > newDF
        ColA ColB ColC
      1  PAR  SYD    Y
      2  NYC  SFO    Y
      

      数据

      df <- structure(list(ColA = c("PAR", "BKK", "NYC", "LAX"), ColB = c("BKK", 
      "SYD", "LAX", "SFO"), ColC = c("Y", "Y", "Y", "Y")), class = "data.frame", row.names = c(NA, 
      -4L))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-21
        • 1970-01-01
        • 2021-12-09
        • 2017-01-29
        • 1970-01-01
        • 2021-03-31
        • 2019-09-27
        • 2013-10-23
        相关资源
        最近更新 更多