Pandas-通过拆分|上的单元格来创建新列n次

时间:2015-08-06 18:53:57

标签: python pandas dataframe

我有一个包含一些调查结果的DataFrame;每列是对问题的回答。但是,对于允许从复选框中获得多个(< 10)答案的问题,该列已将这些答案与“响应1已检查|响应4已检查|响应6已检查...”进行连接,因此我无法只是根据预定义的顺序拆分列,因为它没有说明什么时候没有检查。

ID     NormalResponse    MultipleCheckboxResponse
1      Answer3           Response 3
2      Answer1           Response 1| Response 7
3      Answer2           Response 2| Response 4| Response 7
4      Answer2           Response 2 | Response 3

如何将这些原因拆分为新列,最好只使用布尔标记或单元格中的1/0来确定它是否已标记。

我想看看

ID     NormalResponse    Response1    Response2   Response3     Response4...
1      Answer3           0            0            1            0
2      Answer1           1            0            0            0
3      Answer2           0            1            0            1
4      Answer2           0            1            1            0

3 个答案:

答案 0 :(得分:3)

您可以在执行一些字符串操作后使用get_dummies删除垂直条|周围的空格:

>>> resp = df.MultipleCheckboxResponse.str.replace("[\s]*\|[\s]*", "|")
>>> dummies = resp.str.get_dummies(sep="|")
>>> df.iloc[:,:2].join(dummies)
   ID NormalResponse  Response 1  Response 2  Response 3  Response 4  Response 7
0   1        Answer3           0           0           1           0           0
1   2        Answer1           1           0           0           0           1
2   3        Answer2           0           1           0           1           1
3   4        Answer2           0           1           1           0           0

请注意,这只会为实际看到的响应生成列。如果您想要response6列,即使没有人报告过响应6,那么您需要自己添加循环。

答案 1 :(得分:2)

假设你有一个像这样的数据框

df
#  ID NormalResponse       MultipleCheckboxResponse
#0  1        Answer3                      Response3
#1  2        Answer1            Response1|Response7
#2  3        Answer2  Response2|Response4|Response7
#3  4        Answer2            Response2|Response3

您可以执行以下操作

responses  = df.MultipleCheckboxResponse.unique() # find unique responses in each column
u_response = set( [ x for sublist in responses for x in sublist.split('|') ] ) # find total unique responses in dataframe (maps the 2d list responses to a 1d list)
#{'Response1', 'Response2', 'Response3', 'Response4', 'Response7'}

(注意,set函数仅返回唯一值)。此时,您可以迭代唯一的响应。对于每个响应变量,您应该

  1. 创建匹配响应变量名称
  2. 的数据列
  3. 初始化0
  4. 的每个值
  5. 如果列名称(响应变量)位于MultiCheckboxResponse列中,请检查每一行。如果是,请将行val设置为1。
  6. 循环应该是这样的。

    for col in u_response:
        df[col] = 0 # initialize the col
        df.loc[df.MultipleCheckboxResponse.str.contains(col), col] = 1 # adjust as necessary
    
    df
    #  ID NormalResponse       MultipleCheckboxResponse  Response7  Response4  \
    #0  1        Answer3                      Response3          0          0   
    #1  2        Answer1            Response1|Response7          1          0   
    #2  3        Answer2  Response2|Response4|Response7          1          1   
    #3  4        Answer2            Response2|Response3          0          0   
    
    #   Response2  Response3  Response1  
    #0          0          1          0  
    #1          0          0          1  
    #2          1          0          0  
    #3          1          1          0 
    

    有关处理文本数据的更多建议,请参阅here

    更新

    您似乎有无关的空格,因此您可能希望将u_response代码行更改为

    u_response = set( [ x.strip() for sublist in responses for x in sublist.split('|') ]
    

    我们添加了strip方法。这样您的列标题就没有空格。

答案 2 :(得分:0)

更新:上面至少有一个答案比我的好得多。不要浪费你的时间。

Pandas Series模块具有字符串操作功能,可以在这里派上用场。让我们先尝试一下:

from pandas import Series

response_series = df['MultipleCheckboxResponse']
split_responses = response_series.str.split('|')

这将拆分连锁的回复。返回的系列中的每个元素都是一个包含该行中每个响应的列表。从这里我们可以遍历系列的长度,以及系列中每个列表的长度,将每个单独的响应放在原始数据帧的新列中。

for i in range(0, len(split_responses)):
    for j in range(0, len(split_responses.iloc[i]+1):
        df[j+4][i] = split_responses.iloc[i][j]