使用熊猫处理多答案问卷(来自Google表单)结果

rob*_*ntw 2 python pandas google-forms

我有一个Google表单,该表单用于收集调查数据(对于这个问题,我将使用示例表单),该表单包含可以使用一组复选框选择的多个答案的问题。

当我从表单中获取数据并将其导入大熊猫时,我得到了:

             Timestamp    What sweets do you like?
0  23/11/2013 13:22:30  Chocolate, Toffee, Popcorn
1  23/11/2013 13:22:34                   Chocolate
2  23/11/2013 13:22:39      Toffee, Popcorn, Fruit
3  23/11/2013 13:22:45               Fudge, Toffee
4  23/11/2013 13:22:48                     Popcorn
Run Code Online (Sandbox Code Playgroud)

我想对问题的结果进行统计(有多少人喜欢Chocolate,有多少人喜欢Toffee等)。问题在于,所有答案都在同一列内,因此按该列分组并要求计数是行不通的。

Pandas中是否有一种简单的方法可以将这种数据帧转换成一个包含多个列的数据,分别称为Chocolate,Toffee,Popcorn,Fudge和Fruit,而每个列都是布尔值(1表示是,0表示否)?我想不出一个明智的方法来做到这一点,而且我不确定它是否真的有帮助(以这种方式进行我想做的汇总可能会更困难)。

Moh*_*our 7

几天前我遇到了同样的问题,经过一番搜索,我str.get_dummies在 pandas 文档中找到了函数。让我们看看它是如何工作的:

pandas.Series.str.get_dummies

如文档中所述,按sepstr.get_dummies拆分系列中的每个字符串并返回虚拟/指标变量的 DataFrame。

这是上述 DataFrame 的简化版本:

In [27]: df
Out[27]: 
     What sweets do you like?
0  Chocolate, Toffee, Popcorn
1                   Chocolate
2      Toffee, Popcorn, Fruit
3               Fudge, Toffee
4                     Popcorn
Run Code Online (Sandbox Code Playgroud)

我们需要指定的唯一参数str.get_dummiessep,在我们的例子中是逗号:

In [28]: df['What sweets do you like?'].str.get_dummies(sep=', ')
Out[28]: 
   Chocolate  Fruit  Fudge  Popcorn  Toffee
0          1      0      0        1       1
1          1      0      0        0       0
2          0      1      0        1       1
3          0      0      1        0       1
4          0      0      0        1       0
Run Code Online (Sandbox Code Playgroud)

注意力:

请注意, sep参数中的逗号后面有一个空格,因为空格本身就是一个字符,如果我们不将其包含在sep中,结果将如下所示,这显然是错误的

In [29]: df['What sweets do you like?'].str.get_dummies(sep=',')
Out[29]: 
    Fruit   Popcorn   Toffee  Chocolate  Fudge  Popcorn  Toffee
0       0         1        1          1      0        0       0
1       0         0        0          1      0        0       0
2       1         1        0          0      0        0       1
3       0         0        1          0      1        0       0
4       0         0        0          0      0        1       0
Run Code Online (Sandbox Code Playgroud)

根据经验,请始终注意准确书写分隔符!


Jef*_*eff 6

作为固定宽度表读入,删除第一列

In [30]: df = pd.read_fwf(StringIO(data),widths=[3,20,27]).drop(['Unnamed: 0'],axis=1)

In [31]: df
Out[31]: 
             Timestamp What sweets do you like0
0  23/11/2013 13:22:34                Chocolate
1  23/11/2013 13:22:39   Toffee, Popcorn, Fruit
2  23/11/2013 13:22:45            Fudge, Toffee
3  23/11/2013 13:22:48                  Popcorn
Run Code Online (Sandbox Code Playgroud)

将时间戳记设置为正确的datetime64 dtype(对于本练习不是必需的),但几乎总是您想要的。

In [32]: df['Timestamp'] = pd.to_datetime(df['Timestamp'])
Run Code Online (Sandbox Code Playgroud)

新列名称

In [33]: df.columns = ['date','sweets']

In [34]: df
Out[34]: 
                 date                  sweets
0 2013-11-23 13:22:34               Chocolate
1 2013-11-23 13:22:39  Toffee, Popcorn, Fruit
2 2013-11-23 13:22:45           Fudge, Toffee
3 2013-11-23 13:22:48                 Popcorn

In [35]: df.dtypes
Out[35]: 
date      datetime64[ns]
sweets            object
dtype: object
Run Code Online (Sandbox Code Playgroud)

将Sweet列从字符串拆分为列表

In [37]: df['sweets'].str.split(',\s*')
Out[37]: 
0                 [Chocolate]
1    [Toffee, Popcorn, Fruit]
2             [Fudge, Toffee]
3                   [Popcorn]
Name: sweets, dtype: object
Run Code Online (Sandbox Code Playgroud)

关键一步,这将创建一个虚拟矩阵,用于存在值的地方

In [38]: df['sweets'].str.split(',\s*').apply(lambda x: Series(1,index=x))
Out[38]: 
   Chocolate  Fruit  Fudge  Popcorn  Toffee
0          1    NaN    NaN      NaN     NaN
1        NaN      1    NaN        1       1
2        NaN    NaN      1      NaN       1
3        NaN    NaN    NaN        1     NaN
Run Code Online (Sandbox Code Playgroud)

最终结果,我们将nans填充为0,然后将其类型化为bool以使True / False。然后将其合并到原始框架

In [40]: pd.concat([df,df['sweets'].str.split(',\s*').apply(lambda x: Series(1,index=x)).fillna(0).astype(bool)],axis=1)
Out[40]: 
                 date                  sweets Chocolate  Fruit  Fudge Popcorn Toffee
0 2013-11-23 13:22:34               Chocolate      True  False  False   False  False
1 2013-11-23 13:22:39  Toffee, Popcorn, Fruit     False   True  False    True   True
2 2013-11-23 13:22:45           Fudge, Toffee     False  False   True   False   True
3 2013-11-23 13:22:48                 Popcorn     False  False  False    True  False
Run Code Online (Sandbox Code Playgroud)