【问题标题】:Break a column at regular intervals into multiple rows [duplicate]定期将一列分成多行[重复]
【发布时间】:2018-11-16 04:57:24
【问题描述】:

我在 csv 文件中有一列数字,我想定期拆分该列并将它们转换为多行。例如:

虚拟输入文件:

10
25  
09
04
14
100
01
10
100
04
04
01
04

预期输出(每隔 3 次中断):

10 25 09 
04 14 100
01 10 100
04 04 01
04

我试图在 R 中使用for 循环来执行此操作,但没有成功。我没有得到想要的输出,但在一列中也有超过 1000 万个这样的点。所以我不确定使用循环是否是一种有效的方法。我在 stackexchange 上搜索并看到了其他类似的查询,例如 split string at regular intervalsHow to split a string into substrings of a given length?。但这并没有解决我的问题。

尽管如此,我们对这方面的任何帮助表示赞赏。

【问题讨论】:

    标签: r split rows


    【解决方案1】:

    这是一个动态的tidyverse 方式。应该适用于任何中断值。

    set.seed(1)
    df <- data_frame(x = sample(20, 10))
    
    breaks <- 3
    
    df %>% 
      mutate(
        id = rep(paste0("col", 1:breaks), length.out = nrow(.)),
        rn = ave(x, id, FUN = seq_along)
      ) %>% 
      spread(id, x) %>% 
      select(-rn)
    
    # A tibble: 4 x 3
       col1  col2  col3
      <int> <int> <int>
    1     6     8    11
    2    16     4    14
    3    15     9    19
    4     1    NA    NA
    
    # another example with breaks at 6
    breaks <- 6
    
    df %>% 
      mutate(
        id = rep(paste0("col", 1:breaks), length.out = nrow(.)),
        rn = ave(x, id, FUN = seq_along)
      ) %>% 
      spread(id, x) %>% 
      select(-rn)
    
    # A tibble: 2 x 6
       col1  col2  col3  col4  col5  col6
      <int> <int> <int> <int> <int> <int>
    1     6     8    11    16     4    14
    2    15     9    19     1    NA    NA
    

    【讨论】:

    • 谢谢。它几乎可以工作了。我在处理实际数据时遇到错误Duplicate identifiers for rows (600, 653,...)。对于小的虚拟数据,它工作得很好。
    • 你的休息时间 > 26 吗?如果是这样,您需要将letters[1:breaks] 调整为更合适的值。似乎您每隔 52 次就中断。此外,此问题已被标记为重复,因此请查看原始问题以获取其他答案。
    • 是的。原来我是在11446的间隔断的。letters[1:breaks]需要做哪些修改?
    • 我已更新答案,使其可扩展到任何中断值。试试看,让我知道。
    • 效果很好。谢谢。
    【解决方案2】:

    这是一个基本的 R 选项。我们可以用NA 填充您的输入向量/列,使其长度成为三的倍数。然后,为三列中的每一列生成索引系列,并创建所需的数据框。

    rem <- length(input) %% 3
    input <- c(input, rep(NA, ifelse(rem == 0, 0, 3 - rem)))
    idx1 <- seq(1, length(input), 3)
    idx2 <- seq(2, length(input), 3)
    idx3 <- seq(3, length(input), 3)
    
    df <- data.frame(v1=input[idx1], v2=input[idx2], v3=input[idx3])
    

    【讨论】:

    • 不用于生产,但here is a small demo 表明逻辑有效。
    • 当我们将input 文件作为向量c(1,2,..) 时有效。但是,当我导入包含这些数字的 csv 文件时,它不起作用。
    • @Dark_Knight 那么我的代码只需要稍作修改。我们可以将input替换为数据框/数据表列。
    • read.csv( "my_data.csv" )[ ,1 ] 会给你一个向量
    • 优雅的解决方案。但是如果length(input) 是一个非常大的数字(数百万)并且需要以千级的间隔进行中断,那么将无法手动生成idx 序列。
    【解决方案3】:

    您可以在 dplyr 包中使用 cut 功能。

    dataframe %>% group_by(column) %>% 
    mutate(new_variable = cut(column, breaks=quantile(column, c(0,0.25,0.5,0.75,1), labels=F))
    

    #breaks into the intervals you require 
    new_variable <- cut(as.numeric(dataset$column),breaks = 3) 
    

    然后使用 reshape 包中的 melt 函数将列转置为行

    【讨论】:

      【解决方案4】:

      如果您的数据是向量的形式,您可以执行以下操作:

      data <- c('10', '25', '09', '04', '14', '100', '01',
                '10', '100', '04', '04', '01', '04')
      split(data, ceiling(seq_along(data) / 3))
      

      如果它在数据框中,应该这样做:

      library(dplyr)
      library(tidyr)
      data <- data.frame(
        value = c('10', '25', '09', '04', '14', '100', '01',
              '10', '100', '04', '04', '01', '04'))
      data %>%
        mutate(key = rep_len(c('a', 'b', 'c'), length.out = nrow(.))) %>%
        group_by(idx = as.integer((row_number() - 1) / 3)) %>% 
        spread(key, value) %>%
        select(-idx) %>%
        ungroup()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-24
        • 1970-01-01
        • 1970-01-01
        • 2017-02-06
        • 1970-01-01
        • 2020-01-22
        • 2021-10-08
        • 2013-03-28
        相关资源
        最近更新 更多