python - تحويل القيم إلى أعمدة




pandas (4)

أعتذر عن اسم السؤال الغامض ، لكنني لست متأكدًا من كيفية استدعاء هذه العملية.

لدي إطار البيانات التالي:

import pandas as pd

df = pd.DataFrame({
    'A': [1, 3, 2, 1, 2],
    'B': [2, 1, 3, 2, 3],
    'C': [3, 2, 1, 3, 1],
})
print(df)
#    A  B  C
# 0  1  2  3
# 1  3  1  2
# 2  2  3  1
# 3  1  2  3
# 4  2  3  1

تمثل هذه البيانات "تصنيفًا" لكل خيار من الخيارات ، A و B و C لكل صف. لذلك ، على سبيل المثال ، في الصف 2 ، كان C هو الأفضل ، ثم A ، ثم B أرغب في إنشاء إطار بيانات "مقلوب" ، حيث يوجد لكل صف ثلاثة أعمدة لموضع الترتيب 1 و 2 و 3 ، حيث أصبحت A و B و C هي البيانات الآن. لذلك ، على سبيل المثال أعلاه ، ستكون النتيجة:

out = pd.DataFrame({
    1: ['A', 'B', 'C', 'A', 'C'],
    2: ['B', 'C', 'A', 'B', 'A'],
    3: ['C', 'A', 'B', 'C', 'B'],
})
print(out)
#    1  2  3
# 0  A  B  C
# 1  B  C  A
# 2  C  A  B
# 3  A  B  C
# 4  C  A  B

من الناحية المثالية ، يجب أن يحتوي كل صف في df على القيم الثلاثة المميزة 1 و 2 و 3 ، ولكن قد تكون هناك حالات ذات قيم مكررة (لا يلزم النظر في القيم خارج هذا النطاق). إذا كان ذلك ممكنًا على الإطلاق ، أرغب في حل هذه المشكلة من خلال "تسلسل" أسماء الخيارات الموجودة في نفس الموضع ، ووجود سلاسل فارغة أو NaN في المواضع المفقودة. على سبيل المثال ، باستخدام هذا الإدخال:

df_bad = pd.DataFrame({'A': [1], 'B': [2], 'C': [2]})
print(df_bad)
#    A  B  C
# 0  1  2  2

أريد الحصول على هذا الإخراج بشكل مثالي:

out_bad = pd.DataFrame({1: ['A'], 2: ['BC'], 3: ['']})
print(out_bad)
#    1   2 3
# 0  A  BC

بدلاً من ذلك ، يمكنني التسوية للحصول على إحدى القيم بدلاً من التسلسل.

لقد كنت أبحث عن وظائف melt و pivot و pivot_table وغيرها من الوظائف ، لكن لا يمكنني معرفة طريقة الحصول على النتيجة التي أريدها.


بالنسبة لحالات التصنيف المكررة ، مثل المثال الثاني ، فإن أي حل يستخدم pivot و unstack في الخطوة الأخيرة سوف يفشل. تحتاج إلى pivot_table أو crosstab . كما برزت بالفعل حل باستخدام pivot_table . هنا crosstab

df2 = df_bad.stack().reset_index(1, name='cols')
pd.crosstab(index=df2.index, columns=df2.cols, values=df2.level_1,
                             aggfunc=''.join).fillna('')

Out[171]:
cols   1   2
row_0
0      A  BC

استخدام stack pivot

df.stack().reset_index(1, name='cols').pivot(columns='cols', values='level_1')

Out[131]:
cols  1  2  3
0     A  B  C
1     B  C  A
2     C  A  B
3     A  B  C
4     C  A  B

طريق اخر:

df = pd.DataFrame({
    'A': [1, 3, 2, 1, 2],
    'B': [2, 1, 3, 2, 3],
    'C': [3, 2, 1, 2, 1],
})

(df.stack()
   .reset_index()
   .groupby(['level_0',0])
   .level_1.apply(''.join)
   .unstack()
)

انتاج:

0        1   2    3
level_0            
0        A   B    C
1        B   C    A
2        C   A    B
3        A  BC  NaN
4        C   A    B

يمكن حل المثال الأول الخاص بك بكفاءة مع argsort والفهرسة.

m = np.argsort(df.to_numpy(), 1)

df.columns.to_numpy()[m]

array([['A', 'B', 'C'],
       ['B', 'C', 'A'],
       ['C', 'A', 'B'],
       ['A', 'B', 'C'],
       ['C', 'A', 'B']], dtype=object)

المثال الثاني صعب بعض الشيء ، لكن مع ذلك نفس الفكرة ، سأقوم بالتحديث قريبًا.


يمكنك استخدام argsort :

pd.DataFrame(df.columns.values[np.argsort(df.values)])
   0  1  2
0  A  B  C
1  B  C  A
2  C  A  B
3  A  B  C
4  C  A  B




pandas