2017-08-07 82 views
0

我想根据该模式中的R变换的数据帧:收集多个列入逗号,分隔列表

enter image description here

注意,先前热编码属性Att_1收集为一个逗号在单个单元格中为IDy分隔列表。如何在R中执行此操作(例如,使用tidyr函数)?

test <- data.frame(ID = c("IDx", "IDy"), Att_1_1 = c(0,0), Att_1_2 = c(1,1), Att_1_3 = c(0, 1), Att_2 = c(1,1), Att_3 = c(1,0)) 

回答

3

在基础R,你可以做到以下几点。

# set up new dataframe 
res <- test[-(2:4)] 

# add new varible 
res$Att_1 <- apply(test[, 2:4], 1, function(x) c(names(test)[2:4][as.logical(x)])) 

这里,apply循环通过所述子集data.frame的行和返回的名称,其中行单元的值等于1时,使用逻辑子集的载体。

这将返回

res 
    ID Att_2 Att_3   Att_1 
1 IDx  1  1   Att_1_2 
2 IDy  1  0 Att_1_2, Att_1_3 

注意

res[["Att_1"]] <- ... 

也会起作用。

+0

还有一个问题。我试图通过编写res [,“Att_1”]而不是res $ Att_1来更改代码,但它不起作用。 apply命令返回一个列表。它背后的魔法是什么? ;) – CodingButStillAlive

+0

您可以通过检查'[<。。data.frame'和'$ < - 。data.frame'的代码或多或少地得到一个想法。第一个很长,包含了一些检查,因为'[<-'必须处理比'$ < - '更多的情况。大约3/4通过后,您会看到警告消息的打印输出,后面是'new.cols < - new.cols [seq_len(p)]'行。我相信这会从'apply'截断列表输出以包含第一个元素。 '$ < - '的代码要短得多,并最终使用我在上面的答案中添加的'x [[name]] < - value'。 – lmo

+1

感谢您的全面解释。顺便说一句。我用明确的粘贴代替了这一行,并将其折叠以将元素连接到逗号分隔的字符串中,因为它们在打印输出中以其他方式显示。感谢这真棒的帮助。最好的祝福! – CodingButStillAlive

3

作为OP请求tidyr的功能,我们gather数据集成“长”格式,filter其中“VAL”为1的行中,由“编号”,paste“key”的列进行分组来创建summarise d柱“Att_1”和left_join通过“标识”与原始数据集

library(tidyverse) 
test %>% 
    gather(key, val, Att_1_1:Att_1_3) %>% 
    filter(val==1) %>% 
    group_by(ID) %>% 
    summarise(Att_1 = toString(key)) %>% 
    left_join(df1[-(2:4)], ., by = "ID") %>% 
    select(ID, Att_1, Att_2, Att_3) 
# ID   Att_1 Att_2 Att_3 
#1 IDx   Att_1_2  1  1 
#2 IDy Att_1_2, Att_1_3  1  0 
+1

@Sotos谢谢,我是基于OP显示的图像编码。没有看到OP改变了 – akrun

+0

哇。惊人!非常感谢!但说实话,我真的希望有一个更简单的解决方案。我的意思是......提出的解决方案真的是一门艺术。而我的真实数据框真的非常庞大而复杂。 PS:我编辑帖子以使测试数据帧与图片一致,即ID而不是ID。 – CodingButStillAlive

+0

也许有非tidyr函数更直接的解决方案!? – CodingButStillAlive