所以我有很多带有3列分类变量的pandas数据框:
D F False
T F False
D F False
T F False
第一列和第二列可以采用三个值中的一个。第三个是二进制。因此总共有18个可能的行(并非所有组合都可以在每个数据帧上表示)。
我想为每一行分配一个数字1-18,以便具有相同组合因子的行分配相同的数字,反之亦然(没有哈希冲突)。
在熊猫中最有效的方法是什么?
因此,all_combination_df
是一个df,其中包含所有可能的因素组合。我正在尝试将big_df
之类的df转换为包含唯一数字的系列
import pandas, itertools
def expand_grid(data_dict):
"""Create a dataframe from every combination of given values."""
rows = itertools.product(*data_dict.values())
return pandas.DataFrame.from_records(rows, columns=data_dict.keys())
all_combination_df = expand_grid(
{'variable_1': ['D', 'A', 'T'],
'variable_2': ['C', 'A', 'B'],
'variable_3' : [True, False]})
big_df = pandas.concat([all_combination_df, all_combination_df, all_combination_df])
答案 0 :(得分:4)
更新:作为@user189035 mentioned in the comment,使用分类dtype会更好,因为它可以节省大量内存
我会尝试使用factorize方法:
In [112]: df['category'] = \
...: pd.Categorical(
...: pd.factorize((df.a + '~' + df.b + '~' + (df.c*1).astype(str)))[0])
...:
In [113]: df
Out[113]:
a b c category
0 A X True 0
1 B Y False 1
2 A X True 0
3 C Z False 2
4 A Z True 3
5 C Z True 4
6 B Y False 1
7 C Z False 2
In [114]: df.dtypes
Out[114]:
a object
b object
c bool
category category
dtype: object
说明:这种简单的方法可以将所有列粘合到一个系列中:
In [115]: df.a + '~' + df.b + '~' + (df.c*1).astype(str)
Out[115]:
0 A~X~1
1 B~Y~0
2 A~X~1
3 C~Z~0
4 A~Z~1
5 C~Z~1
6 B~Y~0
7 C~Z~0
dtype: object
答案 1 :(得分:2)
如果不考虑效率问题,这会找到重复的行并为您提供字典(类似于问题here)。
import pandas as pd, numpy as np
# Define data
d = np.array([["D", "T", "D", "T", "U"],
["F", "F", "F", "J", "K"],
[False, False, False, False, True]])
df = pd.DataFrame(d.T)
# Find and remove duplicate rows
df_nodupe = df[~df.duplicated()]
# Make a list
df_nodupe.T.to_dict('list')
{0: ['D', 'F', 'False'],
1: ['T', 'F', 'False'],
3: ['T', 'J', 'False'],
4: ['U', 'K', 'True']}
否则,您可以使用map
,如下所示:
import pandas as pd, numpy as np
# Define data
d = np.array([["D", "T", "D", "T", "U"],
["F", "F", "F", "J", "K"],
[False, False, False, False, True]])
df = pd.DataFrame(d.T)
df.columns = ['x', 'y', 'z']
# Define your dictionary of interest
dd = {('D', 'F', 'False'): 0,
('T', 'F', 'False'): 1,
('T', 'J', 'False'): 2,
('U', 'K', 'True'): 3}
# Create a tuple of the rows of interest
df['tupe'] = zip(df.x, df.y, df.z)
# Create a new column based on the row values
df['new_category'] = df.tupe.map(dd)