【问题标题】:How to change table form of python 3 pandas.DataFrame?如何更改 python 3 pandas.DataFrame 的表格形式?
【发布时间】:2018-03-22 16:38:58
【问题描述】:

我有一个按特定列计数和分组的 pandas 数据框。

import pandas as pd
df = pd.DataFrame({'x':list('aaabbbbbccccc'),'y':list('2225555577777'), 'z':list('1312223224432')})
#
df.groupby(['x','y','z'])['z'].count()
# or
df.groupby(['x','y','z'])['z'].agg(['count'])
# or
df.groupby(['x','y','z'])['z'].count().reset_index(name='counts')

结果是;

   x  y  z  counts
0  a  2  1       2
1  a  2  3       1
2  b  5  2       4
3  b  5  3       1
4  c  7  2       2
5  c  7  3       1
6  c  7  4       2

如何将结果转换为以下形式?

   x  y 1 2 3 4
0  a  2 2 0 1 0
1  b  5 0 4 1 0
2  c  7 0 2 1 2

【问题讨论】:

标签: python python-3.x pandas dataframe


【解决方案1】:

您需要使用unstack + reset_index

(df.groupby(['x','y','z'])['z']
   .count()
   .unstack(-1, fill_value=0)
   .reset_index()
   .rename_axis(None, axis=1)
)

   x  y  1  2  3  4
0  a  2  2  0  1  0
1  b  5  0  4  1  0
2  c  7  0  2  1  2

注意,您可以将 df.groupby(['x','y','z'])['z'].count() 替换为 df.groupby(['x','y','z']).size() 以保持简洁,但请注意 size 也计算 NaN。

【讨论】:

  • 您可以将count 替换为size 并且groupby['z'] 的引用变得不必要了。
  • @piRSquared 糟糕,抱歉,刚刚看到这个帖子。是的,谢谢。会修改。
  • 感谢您的回答和 cmets。我接受这个作为答案,因为这比 Wen 的交叉表快 8 倍,比 piRSquared 的方法快 4 倍。
  • @Sezen 感谢公平仲裁。
【解决方案2】:

类似crosstab

pd.crosstab([df.x,df.y],df.z).reset_index()
Out[81]: 
z  x  y  1  2  3  4
0  a  2  2  0  1  0
1  b  5  0  4  1  0
2  c  7  0  2  1  2

【讨论】:

    【解决方案3】:

    PROJECT/KILL <--(阅读:项目过度杀伤)


    这使用 Pandas factorize 来获取唯一值的整数表示。函数 pd.factorize 以新的整数形式返回传递的数组以及唯一值的数组。

    如果我们对两个位置对应的数组执行此操作,我们可以使用 Numpy 的 bincount 执行交叉制表。

    每次遇到表示“bin”的值时,Bin 计数只会增加一个“bin”。 np.bincount 假设 bin 是来自 0: 的数组索引。因此,如果我想对单个整数数组进行 bin 计数,这开始有意义。但是如何处理二维数组呢?我必须改变我的整数值,以便它们开始在“新行”中计数。我还必须弄清楚那是什么“新行”。来自唯一行值的整数值表示该行。唯一列值的数量代表“移位”

    tups = list(zip(df.x, df.y))
    i, r = pd.factorize(tups)
    j, c = pd.factorize(df.z)
    n, m = len(r), len(c)
    b = np.bincount(i * m + j, minlength=n * m).reshape(n, m)
    
    pd.DataFrame(
        np.column_stack([r.tolist(), b]),
        columns=['x', 'y'] + c.tolist()
    )
    
       x  y  1  3  2  4
    0  a  2  2  1  0  0
    1  b  5  0  1  4  0
    2  c  7  0  1  2  2
    

    对z的排序

    请注意,我使用了 Pandas factorize。我本可以使用 Numpy 的 unique 来做一些事情。但是,我没有这样做的原因有两个。一,np.unique 在返回逆数组时默认对值进行排序(这就是给我分解的原因)。排序的时间复杂度为O(n * log(n)),并且可能会影响较大数组的性能。第二个原因是 Numpy 需要一些额外的烦人处理才能对元组执行任务。

    但是,在这种情况下,我希望看到 z 列以 OP 的相同顺序显示。这要求我在分解时进行排序。我仍然不想使用 Numpy,所以我只使用了 pd.factorize 中的 sort 标志

    tups = list(zip(df.x, df.y))
    i, r = pd.factorize(tups)
    j, c = pd.factorize(df.z, sort=True)
    n, m = len(r), len(c)
    b = np.bincount(i * m + j, minlength=n * m).reshape(n, m)
    
    pd.DataFrame(
        np.column_stack([r.tolist(), b]),
        columns=['x', 'y'] + c.tolist()
    )
    
       x  y  1  2  3  4
    0  a  2  2  0  1  0
    1  b  5  0  4  1  0
    2  c  7  0  2  1  2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-25
      • 2021-08-01
      • 2011-06-22
      • 1970-01-01
      • 1970-01-01
      • 2020-04-05
      • 1970-01-01
      相关资源
      最近更新 更多