Skip to main content
 首页 » 编程设计

python之将具有可变长度逗号分隔值的 pandas Series 转换为 Dataframe

2025年05月04日36over140

我有一个 pandas 系列“A”,其中包含如下逗号分隔值:

index    A 
 
1        null 
2        5,6 
3        3 
4        null 
5        5,18,22 
...      ... 

我需要这样的数据框:

index    A_5    A_6    A_18    A_20 
 
1        0      0      0       ... 
2        1      1      0       ... 
3        0      0      0       ... 
4        0      0      0       ... 
5        1      0      1       ... 
...      ...    ...    ...     ... 

至少未出现 MIN_OBS 次的值应被忽略,并且不会获得自己的列,因为有太多不同的值,如果不应用此阈值,df 会变得太大。

我设计了以下解决方案。它有效,但速度太慢(我想是由于遍历行)。谁能建议更快的方法?

temp_dict = defaultdict(int) 
for k, v in A.iteritems(): 
    temp_list = v.split(',') 
    for item in temp_list: 
        temp_dict[item] += 1 
 
cols_to_make = [] 
for k, v in temp_dict.iteritems(): 
    if v > MIN_OBS: 
        cols_to_make.append('A_' + k) 
 
result_df = pd.DataFrame(0, index = the_series.index, columns = cols_to_make) 
for k, v in A.iteritems(): 
    temp_list = v.split(',') 
    for item in temp_list: 
    if ('A_' + item) in cols_to_make: 
        temp_df['A_' + item][k] = 1 

请您参考如下方法:

您可以使用 get_dummies用于创建指标变量,然后通过 to_numeric 将列转换为数字最后通过变量 TRESH 和 ix 过滤列:

print df 
             A 
index          
1         null 
2          5,6 
3            3 
4         null 
5      5,18,22 
 
df = df.A.str.get_dummies(sep=",") 
print df 
       18  22  3  5  6  null 
index                        
1       0   0  0  0  0     1 
2       0   0  0  1  1     0 
3       0   0  1  0  0     0 
4       0   0  0  0  0     1 
5       1   1  0  1  0     0 
 
df.columns = pd.to_numeric(df.columns, errors='coerce') 
df = df.sort_index(axis=1) 
 
TRESH = 5 
cols = [col for col in df.columns if col > TRESH] 
print cols 
[6.0, 18.0, 22.0] 
df = df.ix[:, cols] 
print df 
       6   18  22 
index             
1       0   0   0 
2       1   0   0 
3       0   0   0 
4       0   0   0 
5       0   1   1 
 
df.columns = ["A_" + str(int(col)) for col in df.columns] 
print df 
       A_6  A_18  A_22 
index                  
1        0     0     0 
2        1     0     0 
3        0     0     0 
4        0     0     0 
5        0     1     1 

编辑:

本人试修改完美原版unutbu answer并更改创建 Series,删除 index 中具有 null 值的 Series 并添加参数 prefix 至 get_dummies :

import numpy as np 
import pandas as pd 
 
s = pd.Series(['null', '5,6', '3', 'null', '5,18,22', '3,4']) 
print s 
 
#result = s.str.split(',').apply(pd.Series).stack() 
#replacing to: 
result = pd.DataFrame([ x.split(',') for x in s ]).stack() 
count = pd.value_counts(result) 
 
min_obs = 2 
 
#add removing Series, which contains null 
count = count[(count >= min_obs) & ~(count.index.isin(['null'])) ] 
 
result = result.loc[result.isin(count.index)] 
#add prefix to function get_dummies 
result = pd.get_dummies(result, prefix="A") 
 
result.index = result.index.droplevel(1) 
result = result.reindex(s.index) 
 
print(result) 
   A_3  A_5 
0  NaN  NaN 
1    0    1 
2    1    0 
3  NaN  NaN 
4    0    1 
5    1    0 

时间:

In [143]: %timeit pd.DataFrame([ x.split(',') for x in s ]).stack() 
1000 loops, best of 3: 866 µs per loop 
 
In [144]: %timeit s.str.split(',').apply(pd.Series).stack() 
100 loops, best of 3: 2.46 ms per loop