[英]Separate rows by matching two columns in similar pattern
我有類似的數據
df1 <- data.frame(A = c("P,Q","X,Y"), B = c("P1,Q1",""), C = c("P2,Q2","X2,Y2"))
我正在尋找像
output <- data.frame(A = c("P","Q","X","Y"), B = c("P1","Q1","",""), C = c("P2","Q2","X2","Y2"))
我嘗試使用如下所述的split_rows,但它與逗號分隔的字符串不匹配。
separate_rows(df1, A, sep=",") %>%
separate_rows(B) %>%
separate_rows(C)
您只需要做:
library(tidyr)
separate_rows(df1, A, B, C, convert = TRUE)
輸出:
A B C
1 P P1 P2
2 Q Q1 Q2
編輯是否有NA
和空字符串:
data:
df1 <- data.frame(A = c("P,Q","X,Y"), B = c("P1,Q1",""), C =
c("P2,Q2","X2,Y2"))
Code:
df1 <- data.frame(lapply(df1, as.character), stringsAsFactors=FALSE)
df1[df1 == ""] <- "0,0"
df1 <- separate_rows(df1, A, B, C, convert = TRUE)
df1[df1 == "0"] <- ""
輸出:
A B C
1 P P1 P2
2 Q Q1 Q2
3 X X2
4 Y Y2
我喜歡進行此類操作的splitstackshape
軟件包,
library(splitstackshape)
cSplit(df1, splitCols = names(df1), sep = ',', direction = 'long')
# A B C
#1: P P1 P2
#2: Q Q1 Q2
將base R
與strsplit
一起使用的選項
data.frame(lapply(df1, function(x) strsplit(as.character(x), ",")[[1]]))
# A B C
#1 P P1 P2
#2 Q Q1 Q2
或帶scan
data.frame(lapply(df1, function(x)
scan(text = as.character(x), what = "", sep=",", quiet = TRUE)))
正如Gainz的答案所建議的那樣,eparate_rows separate_rows(df1, A, B, C, convert = T)
確實工作得很好。
但是,如果數據框中確實有空白單元格,則使用起來確實會更困難,因為這會給您有關所有行數不相同的列的錯誤提示。
我建議使用您知道沒有空白值的列。 假設它是A列。
然后,我首先將數據幀轉換為小標題,然后將所有因子列轉換為字符列。 然后,我將用正確數量的逗號替換字符串中的空白單元格。 然后, separate_rows()
應該能夠正常工作。
然后,代碼將如下所示:
df1_tibble <- df1 %>%
as_tibble() %>%
mutate_if(is.factor, as.character)
df1_clean <- df1_tibble %>%
mutate(count = str_count(A, ",") + 1) %>%
mutate(temp_str = map_chr(count, ~ rep("", .x) %>% paste0(collapse = ","))) %>%
mutate_at(vars(B, C), funs(ifelse(str_length(.) == 0, temp_str, .))) %>%
select(A, B, C)
df1_clean
#> # A tibble: 2 x 3
#> A B C
#> <chr> <chr> <chr>
#> 1 P,Q P1,Q1 P2,Q2
#> 2 X,Y , X2,Y2
df1_clean %>% separate_rows(A, B, C)
#> # A tibble: 4 x 3
#> A B C
#> <chr> <chr> <chr>
#> 1 P P1 P2
#> 2 Q Q1 Q2
#> 3 X "" X2
#> 4 Y "" Y2
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.