有条件地将列值添加为新行

时间:2018-03-21 10:55:40

标签: r

我的csv数据文件格式如下:

DF %>% 
    mutate(Merged = gsub("^,+|,+$", "", gsub(",{2,}", ",", 
       do.call(paste, c(., list(sep=",")))))) %>% 
    separate_rows(Merged, sep=",\\s*")

我想在R

中得到如下结果
1:

101

102

2:

103

104

105

3:

106

107

我使用了for循环,但需要很多时间。原始数据3MB文件。

添加了额外的列" m_id"在test_data数据框中并在代码下执行。

Value       id
101         1
102         1
103         2
104         2
105         2
106         3
107         3

如何在没有for循环的情况下达到上述要求?

3 个答案:

答案 0 :(得分:0)

我们可以使用phantastic tidyverse包含一些逻辑:

library(tidyverse)
junk = "
1:

101

102

2:

103

104

105

3:

106

107"

df <- data_frame(text=junk)
df %>%
  separate_rows(text, sep = '\n') %>%
  filter(text != "") %>%
  extract(text, into = c('group'), regex = "^(\\d+):", remove = FALSE) %>%
  fill(group) %>%
  filter(!grepl("^\\d+:", text)) %>%
  select(group, text)

<小时/> 这产生了

# A tibble: 7 x 2
  group text 
  <chr> <chr>
1 1     101  
2 1     102  
3 2     103  
4 2     104  
5 2     105  
6 3     106  
7 3     107  

答案 1 :(得分:0)

也会起作用:

df <- read.table(col.names = "x",
                 stringsAsFactors = FALSE,
                 text = "1:
101
102
2:
103
104
105
3:
106
107")

retain <- function(x) {
  res <- rep(NA, length(x))
  for (i in seq_along(x)) {
    if (grepl(":", x[i])) {
      res[i] <- x[i]
    } else {
      res[i] <- res[i-1]
    }
  }
  return(res)
} 
df$id <- retain(df$x)
df <- subset(df, id != x)
df$id <- as.numeric(gsub(":", "", df$id))
df

答案 2 :(得分:0)

这是另一个tidyverse解决方案:

library(tidyverse)

df %>% 
  mutate(id = str_detect(V1, ":"),
         id = case_when(id == TRUE ~ V1)) %>% 
  fill(id) %>% 
  filter(V1 != id) %>% 
  mutate(id = str_extract(id, "^(\\d+)"))
   V1 id
1 101  1
2 102  1
3 103  2
4 104  2
5 105  2
6 106  3
7 107  3

我们也可以这样做:

df %>% 
  mutate(id = str_extract(V1, "^(\\d+):"),
         id = str_extract(id, "^(\\d+)")) %>% 
  fill(id) %>% 
  mutate(V1 = str_replace(V1, "^(\\d+):", NA_character_)) %>% 
  drop_na()

数据:

df <- read.table(text = "1:

                 101

                 102

                 2:

                 103

                 104

                 105

                 3:

                 106

                 107", stringsAsFactor = F)