如何在pandas中填充具有重复数据的行?

14

R中,当将长度不相等的新数据添加到数据框中时,值会重复以填充数据框:

df <- data.frame(first=c(1,2,3,4,5,6))
df$second <- c(1,2,3)

产生:

  first second
1     1      1
2     2      2
3     3      3
4     4      1
5     5      2
6     6      3

然而,pandas需要相同长度的索引。

我该如何在pandas中“填充”重复的数据,就像在R中一样?


如果len(df)不是列表长度的完美倍数,请查看此答案 - cs95
8个回答

14

itertools 中的 cycle 方法适用于重复常见的模式。

from itertools import cycle

seq = cycle([1, 2, 3])
df['Seq'] = [next(seq) for count in range(df.shape[0])]

我个人认为这是最好的解决方案。 - chjch

6

似乎没有一种优雅的方式。这是我刚刚想到的解决方法。基本上创建一个重复列表,比原始数据框大,然后进行左连接。

import pandas
df = pandas.DataFrame(range(100), columns=['first'])
repeat_arr = [1, 2, 3]
df = df.join(pandas.DataFrame(repeat_arr * (len(df)/len(repeat_arr)+1),
    columns=['second']))

3
import pandas as pd
import numpy as np

def put(df, column, values):
    df[column] = 0
    np.put(df[column], np.arange(len(df)), values)

df = pd.DataFrame({'first':range(1, 8)})    
put(df, 'second', [1,2,3])

产出收益
   first  second
0      1       1
1      2       2
2      3       3
3      4       1
4      5       2
5      6       3
6      7       1

这个特性可能不太美观,但它有一个好处就是你不需要担心DataFrame的长度是否是重复值长度的倍数。 np.put 会根据需要重复这些值。


我的第一个回答是:

import itertools as IT
df['second'] = list(IT.islice(IT.cycle([1,2,3]), len(df)))

但事实证明,这种方法的速度明显较慢:
In [312]: df = pd.DataFrame({'first':range(10**6)})

In [313]: %timeit df['second'] = list(IT.islice(IT.cycle([1,2,3]), len(df)))
10 loops, best of 3: 143 ms per loop

In [316]: %timeit df['second'] = 0; np.put(df['second'], np.arange(N), [1,2,3])
10 loops, best of 3: 27.9 ms per loop

这很好——尽管在我特定的情况下,如果数字长度不符合要求,我不想填充它们,但对于更普遍的实用性而言可以加1。 - Amyunimus

2
你需要多普遍的解决方案吗?我试图使它不那么硬编码:
import numpy as np
import pandas 

df = pandas.DataFrame(np.arange(1,7), columns=['first'])

base = [1, 2, 3]
df['second'] = base * (df.shape[0]/len(base))
print(df.to_string())


   first  second
0      1       1
1      2       2
2      3       3
3      4       1
4      5       2
5      6       3

1
请注意,第二列赋值只有3个值(而不是6个)。 - Arun
“重复数据”并不是指重复的列。 - Amyunimus

1

在我的情况下,我需要重复值,但不知道子列表的长度,即检查每个组的长度。 这是我的解决方案:

import numpy as np
import pandas 

df = pandas.DataFrame(['a','a','a','b','b','b','b'], columns=['first'])

list = df.groupby('first').apply(lambda x: range(len(x))).tolist()
loop = [val for sublist in list for val in sublist]
df['second']=loop

df
  first  second
0     a       0
1     a       1
2     a       2
3     b       0
4     b       1
5     b       2
6     b       3

1
也许效率不高,但这是一个纯粹的 pandas 解决方案。
import numpy as np
import pandas as pd

base = [1,2,3]
df = pd.DataFrame(data = None,index = np.arange(10),columns = ["filler"])
df["filler"][:len(base)] = base

df["tmp"] = np.arange(len(df)) % len(base)
df["filler"] = df.sort_values("tmp")["filler"].ffill() #.sort_index()
print(df)

1
你可以使用numpy.tile函数来重复一个数组多次。
import numpy as np
import pandas as pd

first = [1, 2, 3, 4, 5, 6]
second = [1, 2, 3]

df = pd.DataFrame({"first": first, "second": np.tile(second, 2)})

print(df)
   first  second
0      1       1
1      2       2
2      3       3
3      4       1
4      5       2
5      6       3

1
你可能想尝试使用取模运算符(%)的功能。你可以使用第一个值(或索引)并将第二个值的长度作为模数来获取你要查找的值(或索引)。类似这样的代码:
df = pandas.DataFrame([0,1,2,3,4,5], columns=['first'])
sec = [0,1,2]
df['second'] = df['first'].apply(lambda x: x % len(sec) )
print(df)
   first  second
0      0       0
1      1       1
2      2       2
3      3       0
4      4       1
5      5       2

我希望这有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接