Повторите строки кадра данных n раз в соответствии с уникальными значениями столбца, и для каждой повторяемой строки создайте новый столбец с различными значениями - PullRequest
0 голосов
/ 05 сентября 2018

Как указано в заголовке, я пытаюсь получить кадр данных с повторением строки. Фактор, который решает, что 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 (который применяет все свои уникальные значения в разных строках).

Ответы [ 3 ]

0 голосов
/ 05 сентября 2018

Одним из решений является преобразование 'Cs' в Категориальное . Затем используйте 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
0 голосов
/ 05 сентября 2018

Создайте еще один DataFrame, используя numpy.unique, и выполните слияние, в результате которого будет получено декартово произведение двух кадров.

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)
0 голосов
/ 05 сентября 2018

Вы можете использовать функцию pivot, а затем fillna для вычисления результата в обоих случаях:

df.pivot('Cs', 'Samp', 'Age').fillna(method='ffill').fillna(method='bfill').unstack().to_frame('Age').reset_index()
...