如何使用R将值动态插入数据帧

如何使用R将值动态插入数据帧,r,dataframe,R,Dataframe,在从一个网站上抓取了一些评论数据之后,我很难将这些数据组织成一个有用的结构进行分析。问题在于,数据是动态的,因为每位评审员对0到3个子类别(表示为子类别“a”、“b”和“c”)进行评分。我想组织评审,使每一行都是不同的评审员,而每一列都是一个子类别。如果评审员选择不给子类别评分,我希望缺失的数据为“NA”。以下是数据的简化示例: vec <- c("a","b","c","stop", "a","b","stop", "stop", "c","stop") ratings <- c(

在从一个网站上抓取了一些评论数据之后,我很难将这些数据组织成一个有用的结构进行分析。问题在于,数据是动态的,因为每位评审员对0到3个子类别(表示为子类别“a”、“b”和“c”)进行评分。我想组织评审,使每一行都是不同的评审员,而每一列都是一个子类别。如果评审员选择不给子类别评分,我希望缺失的数据为“NA”。以下是数据的简化示例:

vec <- c("a","b","c","stop", "a","b","stop", "stop", "c","stop")
ratings <- c(2,5,1, 1,3, 2) 

vec@alexis_laz提供了我认为最好的答案:

vec <- c("a","b","c","stop", "a","b","stop", "stop", "c","stop")
ratings <- c(2,5,1, 1,3, 2) 

stops <- vec == "stop"
i = cumsum(stops)[!stops] + 1L
j = vec[!stops]
tapply(ratings, list(factor(i, 1:max(i)), factor(j)), identity) # although mean/sum work  
#      a  b  c
#[1,]  2  5  1
#[2,]  1  3 NA
#[3,] NA NA NA
#[4,] NA NA  2
vec这里有一个选项

library(data.table)
library(reshape2)
d1 <- as.data.table(melt(split(vec, c(1, head(cumsum(vec == "stop")+1, 
        -1)))))[value != 'stop', ratings := ratings      
        ][value != 'stop'][, value := as.character(value)][, L1 := as.integer(L1)]


dcast( d1[CJ(value = value, L1 = seq_len(max(L1)), unique = TRUE), on = .(value, L1)], 
           L1 ~value, value.var = 'ratings')[, L1 := NULL][]
#    a  b  c
#1:  2  5  1
#2:  1  3 NA
#3: NA NA NA
#4: NA NA  2
库(data.table)
图书馆(E2)

d1使用基本R函数和
rbind.fill
plyr
rbindlist
data.table
生成最终对象,我们可以

# convert vec into a list, split by "stop", dropping final element
temp <- head(strsplit(readLines(textConnection(paste(gsub("stop", "\n", vec, fixed=TRUE),
                                                     collapse=" "))), split=" "), -1)
# remove empty strings, but maintain empty list elements
temp <- lapply(temp, function(x) x[nchar(x) > 0])
# match up appropriate names to the individual elements in the list with setNames
# convert vectors to single row data.frames
temp <- Map(function(x, y) setNames(as.data.frame.list(x), y),
            relist(ratings, skeleton = temp), temp)

# add silly data.frame (single row, single column) for any empty data.frames in list
temp <- lapply(temp, function(x) if(nrow(x) > 0) x else setNames(data.frame(NA), vec[1]))

请注意,
rbind
ing前面的行可以替换为

temp[lengths(temp) == 0] <- replicate(sum(lengths(temp) == 0),
                                      setNames(data.frame(NA), vec[1]), simplify=FALSE)

temp[length(temp)==0]base R,但我使用的是for循环

vec <- c("a","b","c","stop", "a","b","stop", "stop", "c","stop")
ratings <- c(2,5,1, 1,3, 2) 
categories <- unique(vec)[unique(vec)!="stop"]

row = 1
df = data.frame(lapply(categories, function(x){NA_integer_}))
colnames(df) <- categories
rating = 1

for(i in vec) {  
  if(i=='stop') {row <- row+1
  } else { df[row,i] <- ratings[[rating]]; rating <- rating+1}
}

vec这里唯一的问题是你错过了第三位评审员的预期输出数据,他没有给出任何评分。@EvanFriedland Good call。我错过了。添加了一个额外的行来修复这个问题。一个有趣的选项是
relist
,我在删除累积的重复项时,重复了您先前给出的答案。这是一个非常酷的概念,你可以使用骨架参数来匹配另一个对象的结构,同时用新材料填充它。如果你事先知道“a”、“b”、“c”,这是一个非常好的选择。我想我们可以使用
unique(vec)
来构建和填充
df
,修改了答案,这样你就不需要知道或明确指定类别。我不是OP,但我给你+1是因为我喜欢:)我相信这个逻辑的更清晰版本可以是
stops=vec==“stop”;i=累计(停止)[!停止]+1L;j=向量[!停止];tapply(评级,列表(因子(i,1:max(i)),因子(j)),标识)
?这是难以置信的简洁,我自己也不熟悉tapply标识的使用。我认为你的评论显然是个赢家。
vec <- c("a","b","c","stop", "a","b","stop", "stop", "c","stop")
ratings <- c(2,5,1, 1,3, 2) 
categories <- unique(vec)[unique(vec)!="stop"]

row = 1
df = data.frame(lapply(categories, function(x){NA_integer_}))
colnames(df) <- categories
rating = 1

for(i in vec) {  
  if(i=='stop') {row <- row+1
  } else { df[row,i] <- ratings[[rating]]; rating <- rating+1}
}