R Преобразовать пару <ключ, val> в data.frame - PullRequest
7 голосов
/ 15 ноября 2011

В R у меня есть два вектора пар:столбцы x или y должны составлять столбцы, ключи, которые не отображаются в x или y, должны быть добавлены со значением ноль.

Ответы [ 5 ]

9 голосов
/ 15 ноября 2011

Вот подход, основанный на окружающей среде.Создайте отдельные среды, в которые будут оцениваться пары имя = val.Затем объедините их:

xe <- new.env()
ye <- new.env()
with(xe, eval(parse(text=x)))
with(ye, eval(parse(text=y)))
# > ls(env=ye)
# [1] "A" "B" "C" "D" "H"
# edit as. list makes even more compact!
 df1 <- merge(as.list(xe), as.list(ye), all=TRUE, sort=FALSE)  
 # sort keeps row order with x on top!
  A B D  E  F  G  C  H
1 5 1 1  1  2  1 NA NA
2 2 1 1 NA NA NA  3  4

 df1[is.na(df1)] <- 0
 df1
  A B D E F G C H
1 2 1 1 0 0 0 3 4
2 5 1 1 1 2 1 0 0

Проблема с двумя равными аргументами, приводящими к потере одной строки, решается с помощью метода reshape :: rbind.fill.

df1 <- rbind.fill(as.data.frame(as.list(xe)), as.data.frame(as.list(ye)) )
6 голосов
/ 15 ноября 2011

Вот еще один вариант:

x <- c("A=5", "B=1","D=1", "E=1", "F=2", "G=1")
y <- c("A=2", "B=1", "C=3", "D=1","H=4")

# Extract names & values
m <- do.call('cbind', strsplit(x, '='))
xn <- m[1,]
xv <- as.numeric(m[2,])
m <- do.call('cbind', strsplit(y, '='))
yn <- m[1,]
yv <- as.numeric(m[2,])

# Merge names    
an <- sort(union(xn,yn))

# Assemble result
r <- matrix(0, 2, length(an), dimnames=list(NULL, an))
r[1,xn] <- xv
r[2,yn] <- yv

# Inspect result:
r
#     A B C D E F G H
#[1,] 5 1 0 1 1 2 1 0
#[2,] 2 1 3 1 0 0 0 4

# ...if you want a data.frame instead of a matrix:
as.data.frame(r)
#  A B C D E F G H
#1 5 1 0 1 1 2 1 0
#2 2 1 3 1 0 0 0 4
6 голосов
/ 15 ноября 2011

Не самое симпатичное решение, но за ним легко следовать:

1) Разобрать вашу строку во фрейм данных:

df1 <- as.data.frame(sapply(strsplit(x, '='), rbind), stringsAsFactors=FALSE)

Результат:

> as.data.frame(sapply(strsplit(x, '='), rbind), stringsAsFactors=FALSE)
  V1 V2 V3 V4 V5 V6
1  A  B  D  E  F  G
2  5  1  1  1  2  1

2) Дать заголовок:

names(df1) <- df1[1,]
df1 <- df1[-1,]

Результат:

> df1
  A B D E F G
2 5 1 1 1 2 1

3) Сделайте то же самое дляВаша другая строка:

df2 <- as.data.frame(sapply(strsplit(y, '='), rbind), stringsAsFactors=FALSE)
names(df2) <- df2[1,]
df2 <- df2[-1,]

4) Объединить те:

df <- merge(df1, df2, all=TRUE, sort=TRUE)

Результат:

> df
  A B D    E    F    G    C    H
1 2 1 1 <NA> <NA> <NA>    3    4
2 5 1 1    1    2    1 <NA> <NA>

Обновление : вышеупомянутое многофункциональное устройство с косметикой на основе комментариев:

> df1 <- as.data.frame(sapply(strsplit(x, '='), rbind), stringsAsFactors=FALSE)
> names(df1) <- df1[1,]
> df1 <- df1[-1,]
> 
> df2 <- as.data.frame(sapply(strsplit(y, '='), rbind), stringsAsFactors=FALSE)
> names(df2) <- df2[1,]
> df2 <- df2[-1,]
> 
> library(reshape)
> df <- rbind.fill(df1,df2)
> df[is.na(df)] <- 0
> df <- df[, order(names(df))]
> df
  A B C D E F G H
1 5 1 0 1 1 2 1 0
2 2 1 3 1 0 0 0 4
2 голосов
/ 15 ноября 2011

Просто добавляю мое решение.

x <- c("A=11", "B=1", "D=1", "E=1", "F=2", "GZ=1")
y <- c("A=2", "B=1", "C=3", "D=1", "H=4")

pos.x <- as.numeric(regexpr("=", x))
pos.y <- as.numeric(regexpr("=", y))

x.1 <- data.frame(key=substring(x,1,pos.x-1),
                  x=as.numeric(substring(x,pos.x+1)),
                  stringsAsFactors=F)

y.1 <- data.frame(key=substring(y,1,pos.y-1),
                  y=as.numeric(substring(y,pos.y+1)),
                  stringsAsFactors=F)

d <- merge(x.1, y.1, all=T)

d[is.na(d)] <- 0

row.names(d) <- d$key
d$key <- NULL

d <- as.data.frame(t(d))

d
class(d)
1 голос
/ 15 ноября 2011

Другой подход с использованием eval(parse)

vec2list <- function(x){
  x_con <- paste(x, collapse = ",")
  eval(parse(text = paste('list(', x_con, ')')))
}

plyr::ldply(llply(list(x, y), vec2list), data.frame)

  A B D  E  F  G  C  H
1 5 1 1  1  2  1 NA NA
2 2 1 1 NA NA NA  3  4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...