我有一个字符列,每行的值不同。这只是一个小例子:
GoodForMeal %>% head(5)
# A tibble: 5 x 1
GoodForMeal
<chr>
1 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
2 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
3 <NA>
4 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
5 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
以下是该列第一行的dput()
:
structure(list(GoodForMeal = "dessert': False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}"), .Names = "GoodForMeal", row.names = c(NA,
-1L), class = c("tbl_df", "tbl", "data.frame"))
我想将冒号前的值分配为列名,将冒号后的值分配为相应列的值。
示例:
desert latenight lunch diner
1 False False True True
2 False False True True
3 NA NA NA NA
4 False False True True
5 False False True True
我使用tidyr
packadge以及separate
和spread
函数尝试了它:
separate(GoodForMeal, c("key", "value"), sep = ":", extra = "merge") %>% spread(key, value)
问题是r没有在冒号之前拆分所有值,而只是第一个值。
所以结果如下:
GoodForMeal %>% str()
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 4464 obs. of 2 variables:
$ dessert': chr " False, 'latenight': False, 'lunch': True, 'dinner': False, 'breakfast': False, 'brunch': False}" " False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}" " False, 'latenight': False, 'lunch': False, 'dinner': False, 'breakfast': False, 'brunch': False}" " False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}" ...
$ <NA> : chr NA NA NA NA ...
任何想法如何拆分值,使其看起来像在示例中? THX
答案 0 :(得分:1)
使用您提供的测试数据,我会首先使用mutate
删除'
和:
等字符列,以及用餐时间关键字。这允许您拆分分隔各种用餐时间的逗号。以下是一个例子:
df <- structure(list(GoodForMeal = "dessert': False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}"),
.Names = "GoodForMeal", row.names = c(NA, -1L),
class = c("tbl_df", "tbl", "data.frame"))
df %>%
mutate(GoodForMeal = trimws(gsub("[':]|dessert|lunch|dinner|latenight|brunch",
"",
GoodForMeal))) %>%
separate(GoodForMeal,
c("dessert", "latenight", "lunch", "dinner"),
", ",
extra="drop")
它应该产生:
# A tibble: 1 x 4
# dessert latenight lunch dinner
# * <chr> <chr> <chr> <chr>
# False False True True
我希望这证明有用。
答案 1 :(得分:0)
这不是一个优雅的解决方案(而且很长),但似乎有效。我确实更改了数据以使其更通用。希望这可以是一个好的开始。
# i made some changes in the data; remove lunch entry in the 4th element and remove dessert in the 1st
sampleData <- c("'dessert': False, 'latenight': False, 'lunch': True, 'dinner': True",
"'dessert': False, 'latenight': False, 'lunch': True, 'dinner': True",
NA,
"'dessert': False, 'latenight': False, 'dinner': True",
"'latenight': False, 'lunch': True, 'dinner': True")
# [1] "'dessert': False, 'latenight': False, 'lunch': True, 'dinner': True"
# [2] "'dessert': False, 'latenight': False, 'lunch': True, 'dinner': True"
# [3] NA
# [4] "'dessert': False, 'latenight': False, 'dinner': True"
# [5] "'latenight': False, 'lunch': True, 'dinner': True"
# not sure if this is necessary, but jsut to clean the data
sampleData <- gsub(x = sampleData, pattern = "'| ", replacement = "")
# i'm a data.table user, so i'll jsut use tstrsplit
# split the pairs within each elements first
x <- data.table::tstrsplit(sampleData, ",")
# split the header and the entry
test <- lapply(x, function(x) data.table::tstrsplit(x, ":", fixed = TRUE))
# get the headers
indexHeader <- do.call("rbind", lapply(test, function(x) x[[1]]))
# get the entries
indexValue <- do.call("rbind",
lapply(test, function(x){if(length(x) > 1){ return(x[[2]])}else{ return(x[[1]])} }))
# get unique headers
colNames <- unique(as.vector(indexHeader))
colNames <- colNames[!is.na(colNames)]
# determine the order of the entries using the header matrix
indexUse <- apply(indexHeader, 2, function(x) match(colNames, x))
# index the entry matrix using the above matching
resA <- mapply(FUN = function(x,y) x[y],
x = as.data.frame(indexValue),
y = as.data.frame(indexUse))
# convert to data frame
final <- as.data.frame(t(resA))
# rename columns
colnames(final) <- colNames
# should give something like this
final
# dessert latenight lunch dinner
# False False True True
# False False True True
# <NA> <NA> <NA> <NA>
# False False <NA> True
# <NA> False True True