根据唯一的列值重复数据框行 n 次,并对每一行重复创建一个具有不同值的新列
Repeat dataframe rows n times according to the unique column values and to each row repeat create a new column with different values
如标题所述,我正在尝试获取重复行的数据框。
决定 N 次重复执行的因素是基于原始数据帧中特定列的唯一值的长度。
执行重复过程后,我想创建一个新列,将原始数据框特定列的所有相同唯一值应用于创建的每个新行。
我知道这有点令人困惑,但我无法尝试以更好的方式来揭露我的疑问。因此,为了便于您理解我想要的方法,我们提供了一个我的数据框和想要的输出数据框的简短示例:
>> Original Dataframe
Samp Age Cs
1 A 51 msi
2 B 62 cin
3 C 55 msi
4 D 70 ebv
5 E 56 gs
....
如您所见,我的 Cs 列有 4 个唯一值(对于不同的数据帧,它们可能并不总是相同的)。因此,我的目标是获得具有以下结构的数据框:
>> Desired Dataframe
Samp Age Cs
1 A 51 msi
1 A 51 cin
1 A 51 ebv
1 A 51 gs
2 B 62 cin
2 B 62 msi
2 B 62 gs
2 B 62 ebv
3 C 55 msi
3 C 55 cin
3 C 55 ebv
3 C 55 gs
4 D 70 ebv
4 D 70 cin
4 D 70 msi
4 D 70 gs
5 E 56 gs
5 E 56 cin
5 E 56 msi
5 E 56 ebv
....
如您所见,在我想要的数据框中,所有行都重复了 4 次(等于唯一 Cs 列值的数量),但 Cs 列(在不同的行中应用其所有唯一值)。
您可以使用 pivot
函数然后 fillna
这两种方法来计算结果:
df.pivot('Cs', 'Samp', 'Age').fillna(method='ffill').fillna(method='bfill').unstack().to_frame('Age').reset_index()
一个解决方案是将 'Cs'
转换为 Categorical。然后使用 GroupBy
+ first
:
df['Cs'] = df['Cs'].astype('category')
res = df.groupby(['Samp', 'Cs']).first().reset_index()
res['Age'] = res.groupby('Samp')['Age'].transform('first').astype(int)
结果
Samp Cs Age
0 A cin 51
1 A ebv 51
2 A gs 51
3 A msi 51
4 B cin 62
5 B ebv 62
6 B gs 62
7 B msi 62
8 C cin 55
9 C ebv 55
10 C gs 55
11 C msi 55
12 D cin 70
13 D ebv 70
14 D gs 70
15 D msi 70
16 E cin 56
17 E ebv 56
18 E gs 56
19 E msi 56
使用 numpy.unique
创建另一个 DataFrame 并执行合并,这将生成两个帧的笛卡尔积。
s = pd.Series(np.unique(df.Cs.values)).rename('Cs').to_frame()
pd.merge(
df.iloc[:, :2].assign(key=0),
s.assign(key=0),
on='key'
).drop('key', 1)
Samp Age Cs
0 A 51 cin
1 A 51 ebv
2 A 51 gs
3 A 51 msi
4 B 62 cin
5 B 62 ebv
6 B 62 gs
7 B 62 msi
8 C 55 cin
9 C 55 ebv
10 C 55 gs
11 C 55 msi
12 D 70 cin
13 D 70 ebv
14 D 70 gs
15 D 70 msi
16 E 56 cin
17 E 56 ebv
18 E 56 gs
19 E 56 msi
时间
tmp = pd.DataFrame({
'Samp': np.arange(10000),
'Age': np.arange(10000),
'Cs': np.repeat(df.Cs, 2000)
})
In [90]: %%timeit
...: s = pd.Series(np.unique(tmp.Cs.values)).rename('Cs').to_frame()
...: pd.merge(
...: tmp.iloc[:, :2].assign(key=0),
...: s.assign(key=0),
...: on='key'
...: ).drop('key', 1)
...:
10.3 ms ± 92.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [91]: %%timeit
...: tmp['Cs'] = tmp['Cs'].astype('category')
...:
...: res = tmp.groupby(['Samp', 'Cs']).first().reset_index()
...: res['Age'] = res.groupby('Samp')['Age'].transform('first').astype(int)
...:
...:
51.5 ms ± 1.69 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
如标题所述,我正在尝试获取重复行的数据框。 决定 N 次重复执行的因素是基于原始数据帧中特定列的唯一值的长度。 执行重复过程后,我想创建一个新列,将原始数据框特定列的所有相同唯一值应用于创建的每个新行。
我知道这有点令人困惑,但我无法尝试以更好的方式来揭露我的疑问。因此,为了便于您理解我想要的方法,我们提供了一个我的数据框和想要的输出数据框的简短示例:
>> Original Dataframe
Samp Age Cs
1 A 51 msi
2 B 62 cin
3 C 55 msi
4 D 70 ebv
5 E 56 gs
....
如您所见,我的 Cs 列有 4 个唯一值(对于不同的数据帧,它们可能并不总是相同的)。因此,我的目标是获得具有以下结构的数据框:
>> Desired Dataframe
Samp Age Cs
1 A 51 msi
1 A 51 cin
1 A 51 ebv
1 A 51 gs
2 B 62 cin
2 B 62 msi
2 B 62 gs
2 B 62 ebv
3 C 55 msi
3 C 55 cin
3 C 55 ebv
3 C 55 gs
4 D 70 ebv
4 D 70 cin
4 D 70 msi
4 D 70 gs
5 E 56 gs
5 E 56 cin
5 E 56 msi
5 E 56 ebv
....
如您所见,在我想要的数据框中,所有行都重复了 4 次(等于唯一 Cs 列值的数量),但 Cs 列(在不同的行中应用其所有唯一值)。
您可以使用 pivot
函数然后 fillna
这两种方法来计算结果:
df.pivot('Cs', 'Samp', 'Age').fillna(method='ffill').fillna(method='bfill').unstack().to_frame('Age').reset_index()
一个解决方案是将 'Cs'
转换为 Categorical。然后使用 GroupBy
+ first
:
df['Cs'] = df['Cs'].astype('category')
res = df.groupby(['Samp', 'Cs']).first().reset_index()
res['Age'] = res.groupby('Samp')['Age'].transform('first').astype(int)
结果
Samp Cs Age
0 A cin 51
1 A ebv 51
2 A gs 51
3 A msi 51
4 B cin 62
5 B ebv 62
6 B gs 62
7 B msi 62
8 C cin 55
9 C ebv 55
10 C gs 55
11 C msi 55
12 D cin 70
13 D ebv 70
14 D gs 70
15 D msi 70
16 E cin 56
17 E ebv 56
18 E gs 56
19 E msi 56
使用 numpy.unique
创建另一个 DataFrame 并执行合并,这将生成两个帧的笛卡尔积。
s = pd.Series(np.unique(df.Cs.values)).rename('Cs').to_frame()
pd.merge(
df.iloc[:, :2].assign(key=0),
s.assign(key=0),
on='key'
).drop('key', 1)
Samp Age Cs
0 A 51 cin
1 A 51 ebv
2 A 51 gs
3 A 51 msi
4 B 62 cin
5 B 62 ebv
6 B 62 gs
7 B 62 msi
8 C 55 cin
9 C 55 ebv
10 C 55 gs
11 C 55 msi
12 D 70 cin
13 D 70 ebv
14 D 70 gs
15 D 70 msi
16 E 56 cin
17 E 56 ebv
18 E 56 gs
19 E 56 msi
时间
tmp = pd.DataFrame({
'Samp': np.arange(10000),
'Age': np.arange(10000),
'Cs': np.repeat(df.Cs, 2000)
})
In [90]: %%timeit
...: s = pd.Series(np.unique(tmp.Cs.values)).rename('Cs').to_frame()
...: pd.merge(
...: tmp.iloc[:, :2].assign(key=0),
...: s.assign(key=0),
...: on='key'
...: ).drop('key', 1)
...:
10.3 ms ± 92.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [91]: %%timeit
...: tmp['Cs'] = tmp['Cs'].astype('category')
...:
...: res = tmp.groupby(['Samp', 'Cs']).first().reset_index()
...: res['Age'] = res.groupby('Samp')['Age'].transform('first').astype(int)
...:
...:
51.5 ms ± 1.69 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)