将pandas数据框转换为列表

5

I have a pandas dataframe:

apple   banana  carrot  diet coke
1         1       1         0
0         1       0         0
1         0       0         0
1         0       1         1
0         1       1         0
0         1       1         0

我想将它转换为以下内容:

[['apple', 'banana', 'carrot'],
 ['banana'],
 ['apple'],
 ['apple', 'carrot', 'diet coke'],
 ['banana', 'carrot'],
 ['banana', 'carrot']]

我该怎么做呢?非常感谢。

4个回答

6

因为生命短暂,我可能会做一些直接的事情,比如

>>> fruit = [df.columns[row.astype(bool)].tolist() for row in df.values]
>>> pprint.pprint(fruit)
[['apple', 'banana', 'carrot'],
 ['banana'],
 ['apple'],
 ['apple', 'carrot', 'diet coke'],
 ['banana', 'carrot'],
 ['banana', 'carrot']]

这个方法能够生效是因为我们可以使用一个布尔型数组(row.astype(bool))来选择只有在该行为True时 df.columns 中的元素。

非常好的解决方案!现在我的有点尴尬 :) - Pedro M Duarte
太好了!感谢您的回答,即使我不是原帖作者。您能否解释一下在输出列表中如何将元素(在本例中为1)替换为列名?我无法理解这个问题。 - Joe T. Boka
这是一个迷人的解决方案。 - WoodChopper
1
@JoeR,在这个解决方案中,row是一个numpy数组。当你执行row.astype(bool)时,你会得到类似于array([False, True, True, False], dtype=bool)的东西。这个布尔数组可以用来选择性地索引df.columns,它是一个pd.Index对象:df.columns==Index(['apple', 'banana', 'carrot', 'dietcoke'], dtype='object') - Pedro M Duarte
@PedroMDuarte 感谢您的评论,Pedro。我现在开始理解了。 - Joe T. Boka

2

@ DSM解决方案非常棒,但仅当您的值为10时才能工作。如果您需要将其与其他值进行比较,可以尝试以下方法:

[df.columns[df.ix[i,:]==1].tolist() for i in range(len(df.index))]

In [156]: [df.columns[df.ix[i,:]==1].tolist() for i in range(len(df.index))]
Out[156]:
[['apple', 'banana', 'carrot'],
 ['banana'],
 ['apple'],
 ['apple', 'carrot', 'dietcoke'],
 ['banana', 'carrot'],
 ['banana', 'carrot']]

编辑

虽然你可以仅仅修改一下 @DSM 的解决方案:

In [177]: [df.columns[row == 1].tolist() for row in df.values]
Out[177]:
[['apple', 'banana', 'carrot'],
 ['banana'],
 ['apple'],
 ['apple', 'carrot', 'dietcoke'],
 ['banana', 'carrot'],
 ['banana', 'carrot']]

一些性能测试:
In [179]: %timeit [df.columns[row == 1].tolist() for row in df.values]
The slowest run took 4.03 times longer than the fastest. This could mean that an intermediate result is being cached
1000 loops, best of 3: 212 us per loop

In [180]: %timeit [df.columns[row.astype(bool)].tolist() for row in df.values]
10000 loops, best of 3: 186 us per loop

In [181]: %timeit [df.columns[df.ix[i,:]==1].tolist() for i in range(len(df.index))]
100 loops, best of 3: 2.4 ms per loop

1
In [24]: import pandas as pd

In [25]: import io

In [26]: data = """                                          
apple   banana  carrot  dietcoke
1         1       1         0
0         1       0         0
1         0       0         0
1         0       1         1
0         1       1         0
0         1       1         0
"""

In [27]: df = pd.read_csv(io.StringIO(data), delimiter='\s+')

In [28]: df
Out[28]: 
   apple  banana  carrot  dietcoke
0      1       1       1         0
1      0       1       0         0
2      1       0       0         0
3      1       0       1         1
4      0       1       1         0
5      0       1       1         0

In [29]: [[df.columns[i] for i,field in enumerate(record) if field == 1] for j,*record in df.itertuples()]
Out[29]: 
[['apple', 'banana', 'carrot'],
 ['banana'],
 ['apple'],
 ['apple', 'carrot', 'dietcoke'],
 ['banana', 'carrot'],
 ['banana', 'carrot']]

以下是不使用列表推导和扩展元组解包的解决方案:
In [32]: result = []

In [33]: for record in df.itertuples():
   ....:     row = []
   ....:     for i,field in enumerate(record[1:]):
   ....:         if field == 1:
   ....:             row.append(df.columns[i])
   ....:     result.append(row)
   ....: 

In [34]: result
Out[34]: 
[['apple', 'banana', 'carrot'],
 ['banana'],
 ['apple'],
 ['apple', 'carrot', 'dietcoke'],
 ['banana', 'carrot'],
 ['banana', 'carrot']]

文件“<ipython-input-6-565d2353b297>”,第1行 [[df.columns[i] for i,field in enumerate(record) if record[i]==1] for j,*record in df.itertuples()] ^ 语法错误:无效语法 - kevin
你正在运行哪个版本的Python? - Pedro M Duarte
Python 2.7 非常感谢您的帮助! - kevin
已发布。如果备选方案可行,请告诉我。 - Pedro M Duarte
1
嗨Pedro,使用pd.read_clipboard()从问题中复制数据框会更容易。 - WoodChopper
@WoodChopper,谢谢!我不知道pd.read_clipboard() - Pedro M Duarte

1

你可以像Pedro提到的那样遍历并创建,或者只需使用stack()groupby()来列出。

df
Out[14]: 
   apple  banana  carrot  diet_coke
0      1       1       1          0
1      0       1       0          0
2      1       0       0          0
3      1       0       1          1
4      0       1       1          0
5      0       1       1          0

df.stack()
Out[15]: 
0  apple        1
   banana       1
   carrot       1
   diet_coke    0
1  apple        0
   banana       1
   carrot       0
   diet_coke    0
2  apple        1
   banana       0
   carrot       0
   diet_coke    0
3  apple        1
   banana       0
   carrot       1
   diet_coke    1
4  apple        0
   banana       1
   carrot       1
   diet_coke    0
5  apple        0
   banana       1
   carrot       1
   diet_coke    0
dtype: int64



df.stack()[df.stack().values ==1].reset_index()
Out[20]: 
    level_0    level_1  0
0         0      apple  1
1         0     banana  1
2         0     carrot  1
3         1     banana  1
4         2      apple  1
5         3      apple  1
6         3     carrot  1
7         3  diet_coke  1
8         4     banana  1
9         4     carrot  1
10        5     banana  1
11        5     carrot  1


newdf.groupby(['level_0'])['level_1'].apply(list)
Out[27]: 
level_0
0       [apple, banana, carrot]
1                      [banana]
2                       [apple]
3    [apple, carrot, diet_coke]
4              [banana, carrot]
5              [banana, carrot]
Name: level_1, dtype: object

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接