编辑多个列的值并合并为一个列(pandas,python)

1 投票
3 回答
3741 浏览
提问于 2025-04-18 08:37

我想找个方法,用pandas和python把一个Excel表格里几个已知名字的列合并成一个新的列,同时保留所有重要的信息,下面是个例子:

输入:

ID,tp_c,tp_b,tp_p  
0,transportation - cars,transportation - boats,transportation - planes
1,checked,-,-
2,-,checked,-
3,checked,checked,-
4,-,checked,checked
5,checked,checked,checked

想要的输出:

ID,tp_all  
0,transportation  
1,cars  
2,boats  
3,cars+boats  
4,boats+planes  
5,cars+boats+planes 

ID为0的那一行包含了列内容的描述。理想情况下,代码会解析第二行的描述,找到'-'后面的内容,并把这些值合并到新的“tp_all”列里。

3 个回答

1

这里有一种方法:

newCol = pandas.Series('',index=d.index)
for col in d.ix[:, 1:]:
    name = '+' + col.split('-')[1].strip()
    newCol[d[col]=='checked'] += name
newCol = newCol.str.strip('+')

然后:

>>> newCol
0                 cars
1                boats
2           cars+boats
3         boats+planes
4    cars+boats+planes
dtype: object

你可以用这个新列创建一个新的数据表,或者随意处理它。

补充说明:我看到你修改了问题,现在交通方式的名称在第0行,而不是在列标题里。如果把它们放在列标题里会更简单(这是我答案的假设),而且你新的列标题似乎没有包含任何额外有用的信息,所以你可能应该先把列名设置为第0行的信息,然后删除第0行。

3

这真有意思,因为它是一个反向的 get_dummies 操作...

我觉得我会手动处理一下列名,这样你就能得到一个布尔值的数据框:

In [11]: df1  # df == 'checked'
Out[11]:
    cars  boats planes
0
1   True  False  False
2  False   True  False
3   True   True  False
4  False   True   True
5   True   True   True

现在你可以用 zip 和 apply 来处理:

In [12]: df1.apply(lambda row: '+'.join([col for col, b in zip(df1.columns, row) if b]),
                   axis=1)
Out[12]:
0
1                 cars
2                boats
3           cars+boats
4         boats+planes
5    cars+boats+planes
dtype: object

接下来你只需要调整一下表头,就能得到想要的 csv 文件。

如果能有一种更简单或更快的方法来反向操作 get_dummies 就好了...

1

好的,这里有一种更灵活的方法:

In [63]:
# get a list of the columns
col_list = list(df.columns)
# remove 'ID' column
col_list.remove('ID')
# create a dict as a lookup
col_dict = dict(zip(col_list, [df.iloc[0][col].split(' - ')[1] for col in col_list]))
col_dict
Out[63]:
{'tp_b': 'boats', 'tp_c': 'cars', 'tp_p': 'planes'}
In [64]:
# define a func that tests the value and uses the dict to create our string
def func(x):
    temp = ''
    for col in col_list:
        if x[col] == 'checked':
            if len(temp) == 0:
                temp = col_dict[col]
            else:
                temp = temp + '+' + col_dict[col]
    return temp
df['combined'] = df[1:].apply(lambda row: func(row), axis=1)
df
Out[64]:
   ID                   tp_c                    tp_b                     tp_p  \
0   0  transportation - cars  transportation - boats  transportation - planes   
1   1                checked                     NaN                      NaN   
2   2                    NaN                 checked                      NaN   
3   3                checked                 checked                      NaN   
4   4                    NaN                 checked                  checked   
5   5                checked                 checked                  checked   

            combined  
0                NaN  
1               cars  
2              boats  
3         cars+boats  
4       boats+planes  
5  cars+boats+planes  

[6 rows x 5 columns]
In [65]:

df = df.ix[1:,['ID', 'combined']]
df
Out[65]:
   ID           combined
1   1               cars
2   2              boats
3   3         cars+boats
4   4       boats+planes
5   5  cars+boats+planes

[5 rows x 2 columns]

撰写回答