我正在使用 R 为 D3 可视化准备一些数据。可视化是使用以下结构创建的(这是 .csv 文件中的一行,随后在 JavaScript 中转换为 JSON)。
Joe.Schmoe, <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="13797c763d60707b7e7c7653767e727a7f3d707c7e" rel="noreferrer noopener nofollow">[email protected]</a>, Sao Paulo, ["Community01", "Community02", "Community03"],
["workgroup01","workgroup02"]
这是单行。标题将是:
Person, Email, Location, Communities, Workgroups
您会注意到“社区”和“工作组”列包含列表。此外,这些列表的长度会根据每个人所关联的社区和工作组的不同而有所不同。我认识到这可能不是数据“整洁”方面的最佳实践,但这正是该可视化所期望的。
所以......在R(我正在学习)中,我发现不可能重新创建这个结构,因为当我尝试填充“社区”或“工作组”变量时,R似乎期望每个变量将具有相同的长度。
我拥有的代码是从 data.frame 中读取特定社区的成员列表,并将该社区的名称添加到所有员工的主 data.frame 中的列中。我通过电子邮件地址建立索引,因为它是唯一的。因此,这个特定的循环查看名为“commTD”的 data.frame 中的每个单独的电子邮件地址,并在名为“testr”的主 data.frame 中找到它。如果找到它,它会查看社区变量,并用社区名称(在本例中为“技术设计”)替换 NA 值,或者如果向量已存在,则将技术设计附加到其中:
for(i in commTD$email){
if(i %in% testr$email){
tmpList <- testr[which(testr$email ==i) , 'communities']
if(is.na(tmpList)){
tmpList <- list(c("Technical Design"))
}
else{
tmpList <- append(tmpList[[1]][1], 'Technical Design')
}
testr[which(testr$email ==i) , 'communities'] <- list(tmpList)
}
}
这对于初始替换来说效果很好,但是如果我将一个新社区附加到列表中,然后尝试将其传递回 testr data.frame 中,则会收到错误:
Error in `[<-.data.frame`(`*tmp*`, which(testr$email == i), "communities",
: replacement has 2 rows, data has 1
您会注意到,我正在尝试创建一个向量列表,这只是我试图解决这个问题的一种方法。我想也许我可以强制 R 将列表视为单个对象,即使它包含多个项目 - 或者在本例中是多个项目的向量。
在 R 中,将不同长度的向量或列表作为数据框中的单个变量是不可能的吗?
最佳答案
根据定义,数据帧是等长度向量的列表,因此当您询问这是否可以作为类 data.frame() 时,答案是否定的。
您可以按照建议使用另一种类型的对象,例如 data.table,或者另一种方法是将您所需的输出视为不相等向量的列表,以传递给您的 js。
该对象看起来像这样:
dataList <- list(name = c("Joe.Schmoe", "Joe.Bloe"),
email = c("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0b61646e2578686366646e4b6e666a626725686466" rel="noreferrer noopener nofollow">[email protected]</a>", "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="472d282269252b282207222a262e2b6924282a" rel="noreferrer noopener nofollow">[email protected]</a>"),
location = c("Sao Paulo", "London"),
Communities = list(c("Community01", "Community02", "Community03"),
c("Community02", "Community05", "Community03")
),
Workgroups = list(c("workgroup01","workgroup02"),
c("workgroup01","workgroup03"))
)
然后像数据帧一样访问每个字段,以输出到您的js:
dataList$name
dataList$Communities
etc...
根据 Frank 的建议,如果您想通过电子邮件地址访问每个条目,则可以像这样访问每个条目:
data_list[["<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a1cbcec48fd2c2c9cccec4e1c4ccc0c8cd8fc2cecc" rel="noreferrer noopener nofollow">[email protected]</a>"]]
...然后以电子邮件名称作为索引构建列表,如下所示:
data_list = list(`<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3e54515b104d5d5653515b7e5b535f5752105d5153" rel="noreferrer noopener nofollow">[email protected]</a>`=list(name="Joe",
location="Sao Paulo",
Communities=....),
`<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dfb5b0baf1bdb3b0ba9fbab2beb6b3f1bcb0b2" rel="noreferrer noopener nofollow">[email protected]</a>`=list(name="Joe", ...))
然后,您可以避免使用 for() 循环的非 R 风格,并开始享受 lapply() 系列函数的乐趣,以矢量化方式处理所有条目。 (详情请参阅?lapply)
希望有帮助。
关于R 变量中的变长向量或列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30581189/